diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73ab7544d..d6166aad5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: '2.x' + fetch-depth: 0 - name: install altcover run: dotnet tool install --global altcover.visualizer --version 8.6.14 - name: Install dependencies diff --git a/aliyun-net-sdk-core.Tests/Units/Auth/Provider/DefaultCredentialProviderTest.cs b/aliyun-net-sdk-core.Tests/Units/Auth/Provider/DefaultCredentialProviderTest.cs index 55c3162a6..b219dd1d7 100644 --- a/aliyun-net-sdk-core.Tests/Units/Auth/Provider/DefaultCredentialProviderTest.cs +++ b/aliyun-net-sdk-core.Tests/Units/Auth/Provider/DefaultCredentialProviderTest.cs @@ -51,6 +51,20 @@ public void GetAlibabaCloudClientCredentialWithException() Assert.Equal("There is no credential chain can use.", exception.Message); } + [Fact] + public void GetCredentialWithException() + { + var provider = new Mock(); + var defaultProvider = provider.Object; + + var exception = Assert.Throws(() => + { + var credential = defaultProvider.GetCredentials(); + }); + + Assert.Equal("There is no credential chain can use.", exception.Message); + } + /* Case: Test Credential File With default Client Name and file exist with ak value and type Result: should return AccessKeyCredential @@ -97,7 +111,7 @@ public void GetCredentialFileAlibabaCloudCredentialWithAKTypeButAKIsEmpty() TestHelper.DeleteIniFile(); - Assert.Equal("Missing required variable option for 'default Client'", exception.Message); + Assert.Equal("Environment variable roleName('ALIBABA_CLOUD_ECS_METADATA') cannot be empty", exception.Message); } [Fact] @@ -161,11 +175,9 @@ public void GetCredentialFileAlibabaCloudCredentialWithFileAndAkExist() var defaultCredentialProvider = new DefaultCredentialProvider(profile, null); - var credential = (BasicCredentials)defaultCredentialProvider.GetCredentialFileAlibabaCloudCredential(); - + var ex = Assert.Throws(() => (BasicCredentials)defaultCredentialProvider.GetCredentialFileAlibabaCloudCredential()); + Assert.Equal("The configured client type is empty", ex.Message); TestHelper.DeleteIniFile(); - Assert.NotNull(credential); - Assert.Equal("foo", credential.GetAccessKeyId()); } /* @@ -182,10 +194,10 @@ public void GetCredentialFileAlibabaCloudCredentialWithFileAndAkExistNotDefault( var defaultCredentialProvider = new DefaultCredentialProvider(profile, null); - var credential = defaultCredentialProvider.GetCredentialFileAlibabaCloudCredential(); + var ex = Assert.Throws(() => defaultCredentialProvider.GetCredentialFileAlibabaCloudCredential()); + Assert.Equal("The configured client type is empty", ex.Message); TestHelper.DeleteIniFile(); - Assert.Null(credential); } /* @@ -328,15 +340,15 @@ public void GetInstanceRamRoleAlibabaCloudCredential() defaultCredentialProvider.GetInstanceRamRoleAlibabaCloudCredential(); }); - Assert.Equal("RegionID cannot be null or empty.", exception.Message); + Assert.Equal("Environment variable roleName('ALIBABA_CLOUD_ECS_METADATA') cannot be empty", exception.Message); Environment.SetEnvironmentVariable("ALIBABA_CLOUD_REGION_ID", "region_id"); profile.DefaultClientName = "test"; defaultCredentialProvider = new DefaultCredentialProvider(profile, null); - var credentialProvider = defaultCredentialProvider.GetInstanceRamRoleAlibabaCloudCredential(); + var ex = Assert.Throws(() =>defaultCredentialProvider.GetInstanceRamRoleAlibabaCloudCredential()); Environment.SetEnvironmentVariable("ALIBABA_CLOUD_REGION_ID", null); - Assert.Null(credentialProvider); + Assert.Equal("Environment variable roleName('ALIBABA_CLOUD_ECS_METADATA') cannot be empty", exception.Message); } [Fact] @@ -369,13 +381,13 @@ public void GetInstanceRamRoleAlibabaCloudCredential3() Environment.SetEnvironmentVariable("ALIBABA_CLOUD_REGION_ID", "region_id"); profile.DefaultClientName = "default"; var defaultCredentialProvider = new DefaultCredentialProvider(profile, null); - var exception = Assert.Throws(() => + var exception = Assert.Throws(() => { var credentialProvider = defaultCredentialProvider.GetInstanceRamRoleAlibabaCloudCredential(); }); Environment.SetEnvironmentVariable("ALIBABA_CLOUD_REGION_ID", null); - Assert.Equal("You must specifiy a valid role name.", exception.ParamName); + Assert.StartsWith("Environment variable roleName('ALIBABA_CLOUD_ECS_METADATA') cannot be empty", exception.Message); } [Fact] @@ -465,11 +477,10 @@ public void GetRsaKeyPairAlibabaCloudCredential() var defaultCredentialProvider = new DefaultCredentialProvider(profile, "publicKeyId", "privateKeyFile", rsaProvider); - var actualCredentil = defaultCredentialProvider.GetRsaKeyPairAlibabaCloudCredential(); + var ex = Assert.Throws(() => defaultCredentialProvider.GetRsaKeyPairAlibabaCloudCredential()); Environment.SetEnvironmentVariable("ALIBABA_CLOUD_REGION_ID", null); - Assert.NotNull(actualCredentil); - Assert.Equal("aks", actualCredentil.GetAccessKeySecret()); + Assert.Equal("The configured public_key_id or private_key_file is empty", ex.Message); } [Fact] @@ -504,7 +515,7 @@ public void GetRsaKeyPairAlibabaCloudCredentialWithException() var credential = defaultCredentialProvider.GetRsaKeyPairAlibabaCloudCredential(); }); - Assert.Equal("Missing required variable option for 'default Client'", exception.Message); + Assert.Equal("The configured private_key_file is empty", exception.Message); } [Fact] diff --git a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs index ee9c9a608..56f171321 100644 --- a/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/DefaultCredentialProvider.cs @@ -19,14 +19,14 @@ using System; using System.IO; - +using System.Text; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Profile; using Aliyun.Acs.Core.Utils; namespace Aliyun.Acs.Core.Auth.Provider { - public class DefaultCredentialProvider + public class DefaultCredentialProvider : AlibabaCloudCredentialsProvider { private static IClientProfile defaultProfile; @@ -44,38 +44,37 @@ public class DefaultCredentialProvider private string oidcTokenFile; public DefaultCredentialProvider() - { - } - - public DefaultCredentialProvider( - IClientProfile profile, - AlibabaCloudCredentialsProvider alibabaCloudCredentialProvider - ) { accessKeyId = EnvironmentUtil.GetEnvironmentAccessKeyId(); accessKeySecret = EnvironmentUtil.GetEnvironmentAccessKeySecret(); regionId = EnvironmentUtil.GetEnvironmentRegionId(); credentialFileLocation = EnvironmentUtil.GetEnvironmentCredentialFile(); roleName = EnvironmentUtil.GetEnvironmentRoleName(); - defaultProfile = profile; roleArn = EnvironmentUtil.GetEnvironmentRoleArn(); oidcProviderArn = EnvironmentUtil.GetEnvironmentOIDCProviderArn(); oidcTokenFile = EnvironmentUtil.GetEnvironmentOIDCTokenFile(); + } + + [Obsolete] + public DefaultCredentialProvider( + IClientProfile profile, + AlibabaCloudCredentialsProvider alibabaCloudCredentialProvider + ) : this() + { + defaultProfile = profile; this.alibabaCloudCredentialProvider = alibabaCloudCredentialProvider; } + [Obsolete] public DefaultCredentialProvider( IClientProfile profile, string publicKeyId, string privateKeyFile, AlibabaCloudCredentialsProvider alibabaCloudCredentialsProvider - ) + ) : this(profile, alibabaCloudCredentialsProvider) { - defaultProfile = profile; this.privateKeyFile = privateKeyFile; this.publicKeyId = publicKeyId; - regionId = EnvironmentUtil.GetEnvironmentRegionId(); - alibabaCloudCredentialProvider = alibabaCloudCredentialsProvider; } public AlibabaCloudCredentials GetAlibabaCloudClientCredential() @@ -104,6 +103,11 @@ internal virtual AlibabaCloudCredentials GetOIDCAlibabaCloudCredential() public AlibabaCloudCredentials GetEnvironmentAlibabaCloudCredential() { + if (AuthUtils.GetClientType() != "default") + { + return null; + } + if (null == accessKeyId || null == accessKeySecret) { return null; @@ -115,7 +119,7 @@ public AlibabaCloudCredentials GetEnvironmentAlibabaCloudCredential() "Environment credential variable 'ALIBABA_CLOUD_ACCESS_KEY_*' cannot be empty"); } - return defaultProfile.DefaultClientName.Equals("default") ? GetAccessKeyCredential() : null; + return GetAccessKeyCredential(); } public AlibabaCloudCredentials GetCredentialFileAlibabaCloudCredential() @@ -145,26 +149,35 @@ public AlibabaCloudCredentials GetCredentialFileAlibabaCloudCredential() var iniReader = new IniReader(credentialFileLocation); var sectionNameList = iniReader.GetSections(); - if (null != defaultProfile.DefaultClientName) + if (null != defaultProfile) { - var userDefineSectionNode = defaultProfile.DefaultClientName; + var userDefineSectionNode = "default"; var iniKeyTypeValue = iniReader.GetValue("type", userDefineSectionNode); + if(string.IsNullOrEmpty(iniKeyTypeValue)) + { + throw new ClientException("The configured client type is empty"); + } + if (iniKeyTypeValue.Equals("access_key")) { accessKeyId = iniReader.GetValue("access_key_id", userDefineSectionNode); accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); - regionId = iniReader.GetValue("region_id", userDefineSectionNode); - + if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret)) + { + return null; + } return GetAccessKeyCredential(); } if (iniKeyTypeValue.Equals("ecs_ram_role")) { roleName = iniReader.GetValue("role_name", userDefineSectionNode); - regionId = iniReader.GetValue("region_id", userDefineSectionNode); - + if (string.IsNullOrEmpty(roleName)) + { + throw new ClientException("The configured role_name is empty"); + } return GetInstanceRamRoleAlibabaCloudCredential(); } @@ -172,7 +185,17 @@ public AlibabaCloudCredentials GetCredentialFileAlibabaCloudCredential() { accessKeyId = iniReader.GetValue("access_key_id", userDefineSectionNode); accessKeySecret = iniReader.GetValue("access_key_secret", userDefineSectionNode); + if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret)) + { + throw new ClientException("The configured access_key_id or access_key_secret is empty"); + } + roleArn = iniReader.GetValue("role_arn", userDefineSectionNode); + var roleSessionName = iniReader.GetValue("role_session_name", userDefineSectionNode); + if (string.IsNullOrEmpty(roleArn) || string.IsNullOrEmpty(roleSessionName)) + { + throw new ClientException("The configured role_session_name or role_arn is empty"); + } return GetRamRoleArnAlibabaCloudCredential(); } @@ -189,6 +212,7 @@ public AlibabaCloudCredentials GetCredentialFileAlibabaCloudCredential() { foreach (var sectionItem in sectionNameList) { + Console.WriteLine("sectionItem: {0}", sectionItem); if (!sectionItem.Equals("default")) { continue; @@ -197,7 +221,8 @@ public AlibabaCloudCredentials GetCredentialFileAlibabaCloudCredential() accessKeyId = iniReader.GetValue("access_key_id", "default"); accessKeySecret = iniReader.GetValue("access_key_secret", "default"); regionId = iniReader.GetValue("region_id", "default"); - + Console.WriteLine("akkk--{0}", accessKeyId); + Console.WriteLine("skkkk--{0}", accessKeySecret); return GetAccessKeyCredential(); } } @@ -207,14 +232,9 @@ public AlibabaCloudCredentials GetCredentialFileAlibabaCloudCredential() public virtual AlibabaCloudCredentials GetInstanceRamRoleAlibabaCloudCredential() { - if (null == regionId || regionId.Equals("")) + if (string.IsNullOrEmpty(roleName)) { - throw new ClientException("RegionID cannot be null or empty."); - } - - if (!defaultProfile.DefaultClientName.Equals("default")) - { - return null; + throw new ClientException("Environment variable roleName('ALIBABA_CLOUD_ECS_METADATA') cannot be empty"); } InstanceProfileCredentialsProvider instanceProfileCredentialProvider; @@ -233,10 +253,13 @@ public virtual AlibabaCloudCredentials GetInstanceRamRoleAlibabaCloudCredential( public AlibabaCloudCredentials GetAccessKeyCredential() { - if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret) || - string.IsNullOrEmpty(regionId)) + if (accessKeyId == null) { - throw new ClientException("Missing required variable option for 'default Client'"); + throw new ArgumentException("Access key ID cannot be null."); + } + if (accessKeySecret == null) + { + throw new ArgumentException("Access key secret cannot be null."); } var accessKeyCredentialProvider = @@ -247,8 +270,7 @@ public AlibabaCloudCredentials GetAccessKeyCredential() public virtual AlibabaCloudCredentials GetRamRoleArnAlibabaCloudCredential() { - if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret) || - string.IsNullOrEmpty(regionId)) + if (string.IsNullOrEmpty(accessKeyId) || string.IsNullOrEmpty(accessKeySecret)) { throw new ClientException("Missing required variable option for 'default Client'"); } @@ -277,10 +299,24 @@ public virtual AlibabaCloudCredentials GetRamRoleArnAlibabaCloudCredential() public virtual AlibabaCloudCredentials GetRsaKeyPairAlibabaCloudCredential() { - if (string.IsNullOrEmpty(publicKeyId) || string.IsNullOrEmpty(privateKeyFile) || - string.IsNullOrEmpty(regionId)) + if (string.IsNullOrEmpty(privateKeyFile)) { - throw new ClientException("Missing required variable option for 'default Client'"); + throw new ClientException("The configured private_key_file is empty"); + } + + string privateKey; + try + { + privateKey = File.ReadAllText(privateKeyFile, Encoding.UTF8); + } + catch (IOException) + { + privateKey = null; + } + + if (string.IsNullOrEmpty(publicKeyId) || string.IsNullOrEmpty(privateKey)) + { + throw new ClientException("The configured public_key_id or private_key_file is empty"); } var rsaKeyPairCredential = new KeyPairCredentials(publicKeyId, privateKeyFile); @@ -304,5 +340,20 @@ public virtual string GetHomePath() { return EnvironmentUtil.GetHomePath(); } + + public AlibabaCloudCredentials GetCredentials() + { + var credential = GetEnvironmentAlibabaCloudCredential() ?? + GetOIDCAlibabaCloudCredential() ?? + GetCredentialFileAlibabaCloudCredential() ?? + GetInstanceRamRoleAlibabaCloudCredential(); + + if (credential == null) + { + throw new ClientException("There is no credential chain can use."); + } + + return credential; + } } } diff --git a/aliyun-net-sdk-core/Auth/Provider/InstanceProfileCredentialsProvider.cs b/aliyun-net-sdk-core/Auth/Provider/InstanceProfileCredentialsProvider.cs index b5084ca88..1cc8b1bf3 100644 --- a/aliyun-net-sdk-core/Auth/Provider/InstanceProfileCredentialsProvider.cs +++ b/aliyun-net-sdk-core/Auth/Provider/InstanceProfileCredentialsProvider.cs @@ -17,6 +17,7 @@ * under the License. */ +using System; using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Utils; @@ -63,15 +64,18 @@ public virtual AlibabaCloudCredentials GetCredentials() } catch (ClientException ex) { - if (ex.ErrorCode.Equals("SDK.SessionTokenExpired") && - ex.ErrorMessage.Equals("Current session token has expired.")) + if (ex.ErrorCode != null && ex.ErrorCode.Equals("SDK.SessionTokenExpired") && + ex.ErrorMessage != null && ex.ErrorMessage.Equals("Current session token has expired.")) { CommonLog.LogException(ex, ex.ErrorCode, ex.ErrorMessage); throw new ClientException(ex.ErrorCode, ex.ErrorMessage); } // Use the current expiring session token and wait for next round - credentials.SetLastFailedRefreshTime(); + if (credentials != null) + { + credentials.SetLastFailedRefreshTime(); + } } return credentials; diff --git a/aliyun-net-sdk-core/Utils/AuthUtils.cs b/aliyun-net-sdk-core/Utils/AuthUtils.cs index 137ffe918..4de57966f 100644 --- a/aliyun-net-sdk-core/Utils/AuthUtils.cs +++ b/aliyun-net-sdk-core/Utils/AuthUtils.cs @@ -28,12 +28,22 @@ namespace Aliyun.Acs.Core.Utils public class AuthUtils { private static volatile string oidcToken; + private static volatile string clientType = Environment.GetEnvironmentVariable("ALIBABA_CLOUD_PROFILE"); AuthUtils() { } - + public static string GetClientType() + { + if (clientType == null) + { + AuthUtils.clientType = "default"; + } + return AuthUtils.clientType; + } + + public static string GetOIDCToken(string OIDCTokenFilePath) { byte[] buffer;