/// <summary>
        /// Translates enum into a friendlier 'from xxx' display string
        /// </summary>
        /// <param name="creds"></param>
        /// <returns></returns>
        internal static string FormatCredentialSourceForDisplay(AWSPSCredentials creds)
        {
            switch (creds.Source)
            {
            case CredentialsSource.CredentialsObject:
                return("supplied credentials object");

            case CredentialsSource.Container:
                return("container environment");

            case CredentialsSource.InstanceProfile:
                return("instance profile");

            case CredentialsSource.Profile:
                return(String.Format("stored profile named '{0}'", creds.Name));

            case CredentialsSource.Session:
                return("shell variable $" + SessionKeys.AWSCredentialsVariableName);

            case CredentialsSource.Strings:
                return("the supplied key parameters");
            }

            // fallback
            return(Enum.GetName(typeof(CredentialsSource), creds.Source));
        }
Пример #2
0
        /// <summary>
        /// Try to obtain an <see cref="AWSCredentials"/> from the PowerShell session variable <c>StoredAWSCredentials</c> by reflection.
        /// Because we have duplicated some of the credential classes we have conflicting types, therefore we have to get to the underlying
        /// common credentials using reflection.
        /// </summary>
        /// <param name="sessionVariableValue">The session variable value.</param>
        /// <param name="credentials">The credentials.</param>
        /// <returns><c>true</c> if credentials obtained from PowerShell session; else <c>false</c>.</returns>
        private static bool TryGetAWSPSCredentialsFromConflictingType(object sessionVariableValue, out AWSPSCredentials credentials)
        {
            credentials = null;

            if (sessionVariableValue == null)
            {
                return(false);
            }

            var properties = sessionVariableValue.GetType().GetProperties(
                System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

            var credentialsProperty =
                properties.FirstOrDefault(p => typeof(AWSCredentials).IsAssignableFrom(p.PropertyType));

            var nameProperty = properties.FirstOrDefault(p => p.Name == "Name" && p.PropertyType == typeof(string));

            if (credentialsProperty != null)
            {
                credentials = new AWSPSCredentials(
                    (AWSCredentials)credentialsProperty.GetValue(sessionVariableValue),
                    nameProperty != null ? (string)nameProperty.GetValue(sessionVariableValue) : "none",
                    CredentialsSource.Session);
                return(true);
            }

            return(false);
        }
 /// <summary>
 /// Safely emit a diagnostic message indicating where the credentials we are about to use
 /// originated from.
 /// </summary>
 /// <param name="awsPSCredentials"></param>
 protected void WriteCredentialSourceDiagnostic(AWSPSCredentials awsPSCredentials)
 {
     try
     {
         WriteCredentialSourceDiagnostic(FormatCredentialSourceForDisplay(awsPSCredentials));
     }
     catch
     {
     }
 }
        /// <summary>
        /// update the custom state we have applied to hold the host and any network credential
        /// the user has supplied to us as a shell default to fall back on if we get called to
        /// show the password dialog
        /// </summary>
        /// <param name="currentCredentials"></param>
        private void SetUpIfFederatedCredentials(AWSPSCredentials currentCredentials)
        {
            var callbackState = (currentCredentials.Credentials as FederatedAWSCredentials)?.Options.CustomCallbackState as SAMLCredentialCallbackState;

#if DESKTOP
            if (callbackState == null)
            {
#pragma warning disable CS0618 //A class was marked with the Obsolete attribute
                callbackState = (currentCredentials.Credentials as StoredProfileFederatedCredentials)?.CustomCallbackState as SAMLCredentialCallbackState;
#pragma warning restore CS0618 //A class was marked with the Obsolete attribute
            }
#endif

            if (callbackState != null) // is our callback that's attached
            {
                callbackState.ShellNetworkCredentialParameter = NetworkCredential;
            }
        }
        private void GetFromCommandLine(out AWSPSCredentials awsPSCredentialsFromCommandLine, out RegionEndpoint regionFromCommandLine)
        {
            // Retrieve credentials if passed in (or from Instance Profile)
            if (this.TryGetCredentials(Host, out awsPSCredentialsFromCommandLine, SessionState))
            {
                WriteVerbose(string.Format("{0}: Credentials for this shell were set from {1}",
                                           MyInvocation.MyCommand.Name,
                                           ServiceCmdlet.FormatCredentialSourceForDisplay(awsPSCredentialsFromCommandLine)));
            }

            RegionSource regionSource;

            if (this.TryGetRegion(true, out regionFromCommandLine, out regionSource, SessionState))
            {
                WriteVerbose(string.Format("{0}: Region '{1}' was set for this shell from {2}",
                                           MyInvocation.MyCommand.Name,
                                           regionFromCommandLine.SystemName,
                                           ServiceCmdlet.FormatRegionSourceForDisplay(regionSource)));
            }
        }
        protected override void ProcessRecord()
        {
            AWSPSCredentials currentCredentials = null;

            if (this.TryGetCredentials(Host, out currentCredentials, SessionState))
            {
                // used to be equivalent of write-host but got customer feedback that the inability to
                // suppress it interfered with console output (https://forums.aws.amazon.com/thread.jspa?threadID=211600&tstart=0).
                WriteVerbose(InitializeDefaultConfigurationCmdlet.CredentialsSourceMessage(currentCredentials));
            }
            else
            {
                this.ThrowTerminatingError(new ErrorRecord(new ArgumentException("Cannot determine credentials from supplied parameters"),
                                                           "ArgumentException", ErrorCategory.InvalidArgument, this));
            }

            if (currentCredentials != null)
            {
                WriteObject(currentCredentials.Credentials);
            }
        }
        private void GetFromDefaultProfile(out AWSPSCredentials awsPSCredentialsFromDefaultProfile, out RegionEndpoint regionFromDefaultProfile)
        {
            CredentialProfile profile;

            if (SettingsStore.TryGetProfile(SettingsStore.PSDefaultSettingName, ProfileLocation, out profile))
            {
                AWSCredentials defaultAWSCredentials;
                if (SettingsStore.TryGetAWSCredentials(SettingsStore.PSDefaultSettingName, ProfileLocation, out defaultAWSCredentials))
                {
                    awsPSCredentialsFromDefaultProfile = new AWSPSCredentials(defaultAWSCredentials, SettingsStore.PSDefaultSettingName, CredentialsSource.Profile);
                }
                else
                {
                    awsPSCredentialsFromDefaultProfile = null;
                }

                regionFromDefaultProfile = profile.Region;
            }
            else
            {
                awsPSCredentialsFromDefaultProfile = null;
                regionFromDefaultProfile           = null;
            }
        }
Пример #8
0
        public static bool TryGetCredentials(
            this IAWSCredentialsArguments self,
            PSHost psHost,
            out AWSPSCredentials credentials,
            SessionState sessionState)
        {
            if (self == null)
            {
                throw new ArgumentNullException("self");
            }

            credentials = null;
            string name   = null;
            var    source = CredentialsSource.Unknown;
            var    userSpecifiedProfile = !string.IsNullOrEmpty(self.ProfileName);

            var profileChain = new CredentialProfileStoreChain(self.ProfileLocation);

            // we probe for credentials by first checking the bound parameters to see if explicit credentials
            // were supplied (keys, profile name, credential object), overriding anything in the shell environment
            if (AWSCredentialsFactory.TryGetAWSCredentials(
                    self.GetCredentialProfileOptions(),
                    profileChain,
                    out var innerCredentials))
            {
                source = CredentialsSource.Strings;
                name   = "Supplied Key Parameters";
                SetProxyAndCallbackIfNecessary(innerCredentials, self, psHost, sessionState);
            }

            // user gave us the profile name?
            if (innerCredentials == null && userSpecifiedProfile)
            {
                if (profileChain.TryGetProfile(self.ProfileName, out var credentialProfile))
                {
                    innerCredentials = AWSCredentialsFactory.GetAWSCredentials(credentialProfile, profileChain);
                    source           = CredentialsSource.Profile;
                    name             = self.ProfileName;
                    SetProxyAndCallbackIfNecessary(innerCredentials, self, psHost, sessionState);
                }
                else
                {
                    // if the user gave us an explicit profile name (and optional location) it's an error if we
                    // don't find it as otherwise we could drop through and pick up a 'default' profile that is
                    // for a different account
                    return(false);
                }
            }

            // how about an aws credentials object?
            if (innerCredentials == null && self.Credential != null)
            {
                innerCredentials = self.Credential;
                source           = CredentialsSource.CredentialsObject;
                name             = "Credentials Object";

                // don't set proxy and callback, use self.Credential as-is
            }

            // shell session variable set (this allows override of machine-wide environment variables)
            if (innerCredentials == null && sessionState != null)
            {
                if (TryGetAWSPSCredentialsFromConflictingType(
                        sessionState.PSVariable.GetValue(SessionKeys.AWSCredentialsVariableName),
                        out var psCredentials))
                {
                    credentials      = psCredentials;
                    source           = CredentialsSource.Session;
                    innerCredentials = credentials.Credentials; // so remaining probes are skipped

                    // don't set proxy and callback, use credentials.Credentials as-is
                }
            }

            // no explicit command-level or shell instance override set, start to inspect the environment
            // starting environment variables
            if (innerCredentials == null)
            {
                try
                {
                    var environmentCredentials = new EnvironmentVariablesAWSCredentials();
                    innerCredentials = environmentCredentials;
                    source           = CredentialsSource.Environment;
                    name             = "Environment Variables";

                    // no need to set proxy and callback - only basic or session credentials
                }
                catch
                {
                }
            }

            // get credentials from a 'default' profile?
            if (innerCredentials == null && !userSpecifiedProfile)
            {
                if (profileChain.TryGetProfile(SettingsStore.PSDefaultSettingName, out var credentialProfile) &&
                    credentialProfile.CanCreateAWSCredentials)
                {
                    innerCredentials = AWSCredentialsFactory.GetAWSCredentials(credentialProfile, profileChain);
                    source           = CredentialsSource.Profile;
                    name             = SettingsStore.PSDefaultSettingName;
                    SetProxyAndCallbackIfNecessary(innerCredentials, self, psHost, sessionState);
                }
            }

            // get credentials from a legacy default profile name?
            if (innerCredentials == null)
            {
                if (profileChain.TryGetProfile(SettingsStore.PSLegacyDefaultSettingName, out var credentialProfile) &&
                    credentialProfile.CanCreateAWSCredentials)
                {
                    if (AWSCredentialsFactory.TryGetAWSCredentials(
                            credentialProfile,
                            profileChain,
                            out innerCredentials))
                    {
                        source = CredentialsSource.Profile;
                        name   = SettingsStore.PSLegacyDefaultSettingName;
                        SetProxyAndCallbackIfNecessary(innerCredentials, self, psHost, sessionState);
                    }
                }
            }

            if (innerCredentials == null)
            {
                // try and load credentials from ECS endpoint (if the relevant environment variable is set)
                // or EC2 Instance Profile as a last resort
                try
                {
                    var relativeUri =
                        Environment.GetEnvironmentVariable(ECSTaskCredentials.ContainerCredentialsURIEnvVariable);
                    var fullUri = Environment.GetEnvironmentVariable(
                        ECSTaskCredentials.ContainerCredentialsFullURIEnvVariable);

                    if (!string.IsNullOrEmpty(relativeUri) || !string.IsNullOrEmpty(fullUri))
                    {
                        innerCredentials = new ECSTaskCredentials();
                        source           = CredentialsSource.Container;
                        name             = "Container";

                        // no need to set proxy and callback
                    }
                    else
                    {
                        innerCredentials = new InstanceProfileAWSCredentials();
                        source           = CredentialsSource.InstanceProfile;
                        name             = "Instance Profile";

                        // no need to set proxy and callback
                    }
                }
                catch
                {
                    innerCredentials = null;
                }
            }

            if (credentials == null && innerCredentials != null)
            {
                credentials = new AWSPSCredentials(innerCredentials, name, source);
            }

            return(credentials != null);
        }
        protected override void ProcessRecord()
        {
            AWSPSCredentials currentCredentials = null;

            if (this.TryGetCredentials(Host, out currentCredentials, SessionState))
            {
                WriteVerbose(InitializeDefaultConfigurationCmdlet.CredentialsSourceMessage(currentCredentials));

                if (string.IsNullOrEmpty(StoreAs))
                {
                    SetUpIfFederatedCredentials(currentCredentials);
                    string scope = MyInvocation.BoundParameters.ContainsKey("Scope") ? Scope.ToString() + ":" : "";
                    this.SessionState.PSVariable.Set(scope + SessionKeys.AWSCredentialsVariableName, currentCredentials);
                }
                else
                {
                    if (MyInvocation.BoundParameters.ContainsKey("Scope"))
                    {
                        this.ThrowTerminatingError(new ErrorRecord(
                                                       new ArgumentException("Parameters Scope and StoreAs cannot be used together."),
                                                       "ArgumentException", ErrorCategory.InvalidArgument, this));
                    }

                    if (string.Equals(AWSCredentialsArgumentsFullCmdlet.AWSCredentialsObjectSet, ParameterSetName, StringComparison.Ordinal))
                    {
                        // We're storing from the -Credential parameter to a credentials file.
                        // Only some types of AWSCredentials are supported.
                        var options = CredentialProfileOptionsExtractor.ExtractProfileOptions(currentCredentials.Credentials);
                        if (options != null)
                        {
                            SettingsStore.RegisterProfile(options, StoreAs, ProfileLocation, null);
                        }
                    }
                    else
                    {
                        if (string.Equals(AWSCredentialsArgumentsFullCmdlet.StoredProfileSet, ParameterSetName, StringComparison.Ordinal))
                        {
                            // We're copying from one profile to another.
                            var chain = new CredentialProfileStoreChain(ProfileLocation);
                            CredentialProfile profile;
                            if (chain.TryGetProfile(ProfileName, out profile))
                            {
                                profile.CredentialProfileStore.CopyProfile(ProfileName, StoreAs, true);
                            }
                            else
                            {
                                // Parameters.TryGetCredentials has already tested for this but...
                                this.ThrowTerminatingError(new ErrorRecord(
                                                               new ArgumentException("Cannot determine credentials from supplied parameters"),
                                                               "ArgumentException", ErrorCategory.InvalidArgument, this));
                            }
                        }
                        else
                        {
                            // We're storing from individual command line values to a credentials file.
                            SettingsStore.RegisterProfile(GetCredentialProfileOptions(), StoreAs, ProfileLocation, null);
                        }
                    }

                    if (string.IsNullOrEmpty(ProfileLocation))
                    {
                        WriteVerbose("Updated .NET credentials file.");
                    }
                    else
                    {
                        WriteVerbose("Updated shared credentials file at " + ProfileLocation);
                    }
                }
            }
            else
            {
                this.ThrowTerminatingError(new ErrorRecord(new ArgumentException("Cannot determine credentials from supplied parameters"),
                                                           "ArgumentException",
                                                           ErrorCategory.InvalidArgument,
                                                           this));
            }
        }
        protected override void ProcessRecord()
        {
            AWSPSCredentials awsPSCredentialsFromCommandLine;
            RegionEndpoint   regionFromCommandLine;
            AWSPSCredentials awsPSCredentialsFromDefaultProfile;
            RegionEndpoint   regionFromDefaultProfile;
            AWSPSCredentials awsPSCredentialsFromPromptingUser = null;
            RegionEndpoint   regionFromPromptingUser           = null;

            // get what was passed in on the command line, and what's already in defaults
            GetFromCommandLine(out awsPSCredentialsFromCommandLine, out regionFromCommandLine);
            GetFromDefaultProfile(out awsPSCredentialsFromDefaultProfile, out regionFromDefaultProfile);

            // if the command line and defaults don't provide us what we need then prompt the user
            if (awsPSCredentialsFromCommandLine == null && awsPSCredentialsFromDefaultProfile == null)
            {
                awsPSCredentialsFromPromptingUser = PromptUserForCredentials();
            }

            if (regionFromCommandLine == null && regionFromDefaultProfile == null)
            {
                regionFromPromptingUser = PromptUserForRegion();
            }

            // figure out what needs to be saved to disk and what needs to get put in session
            var awsPSCredentialsToPersist      = awsPSCredentialsFromCommandLine == null ? awsPSCredentialsFromPromptingUser : awsPSCredentialsFromCommandLine;
            var awsPSCredentialsToPutInSession = awsPSCredentialsToPersist == null ? awsPSCredentialsFromDefaultProfile : awsPSCredentialsToPersist;

            var regionToPersist      = regionFromCommandLine == null ? regionFromPromptingUser : regionFromCommandLine;
            var regionToPutInSession = regionToPersist == null ? regionFromDefaultProfile : regionToPersist;

            // save credentials and region to disk if necessary
            if (awsPSCredentialsToPersist != null || regionToPersist != null)
            {
                if (string.Equals(AWSCredentialsArgumentsFullCmdlet.AWSCredentialsObjectSet, ParameterSetName, StringComparison.Ordinal))
                {
                    // We're storing from the -Credential parameter to a credentials file.
                    // Only some types of AWSCredentials are supported.
                    var options = CredentialProfileOptionsExtractor.ExtractProfileOptions(awsPSCredentialsToPersist.Credentials);
                    if (options != null)
                    {
                        SettingsStore.RegisterProfile(options, SettingsStore.PSDefaultSettingName, ProfileLocation, regionToPersist);
                    }
                }
                else
                {
                    if (string.Equals(AWSCredentialsArgumentsFullCmdlet.StoredProfileSet, ParameterSetName, StringComparison.Ordinal))
                    {
                        // We're copying from one profile to another.
                        var chain = new CredentialProfileStoreChain(ProfileLocation);
                        CredentialProfile profile;
                        if (chain.TryGetProfile(ProfileName, out profile))
                        {
                            profile.CredentialProfileStore.CopyProfile(ProfileName, SettingsStore.PSDefaultSettingName, true);
                            SettingsStore.RegisterProfile(new CredentialProfileOptions(), SettingsStore.PSDefaultSettingName, ProfileLocation, regionToPersist);
                        }
                        else
                        {
                            // Parameters.TryGetCredentials has already tested for this but...
                            this.ThrowTerminatingError(new ErrorRecord(
                                                           new ArgumentException("Cannot determine credentials from supplied parameters"),
                                                           "ArgumentException", ErrorCategory.InvalidArgument, this));
                        }
                    }
                    else
                    {
                        // We're storing from individual command line values to the default profile.
                        SettingsStore.RegisterProfile(GetCredentialProfileOptions(), SettingsStore.PSDefaultSettingName, ProfileLocation, regionToPersist);
                    }
                }

                if (string.IsNullOrEmpty(ProfileLocation))
                {
                    WriteVerbose("Updated SDK profile store.");
                }
                else
                {
                    WriteVerbose("Updated credential file at " + ProfileLocation);
                }
                WriteVerbose(string.Format("Default credentials and/or region have been stored to credentials profile '{0}' and set active for this shell.", SettingsStore.PSDefaultSettingName));
            }

            string scope = MyInvocation.BoundParameters.ContainsKey("Scope") ? Scope.ToString() + ":" : "";

            // put credentials and region in session
            this.SessionState.PSVariable.Set(scope + SessionKeys.AWSCredentialsVariableName, awsPSCredentialsToPutInSession);
            this.SessionState.PSVariable.Set(scope + SessionKeys.AWSRegionVariableName, regionToPutInSession.SystemName);
        }
 internal static string CredentialsSourceMessage(AWSPSCredentials creds)
 {
     return(string.Format(CredentialsSourceMsg, ServiceCmdlet.FormatCredentialSourceForDisplay(creds)));
 }