【问题标题】:upload x509 certificate to azure application manifest programmatically以编程方式将 x509 证书上传到 Azure 应用程序清单
【发布时间】:2018-07-05 19:15:39
【问题描述】:

有没有办法以编程方式将在 Visual Studios 中创建的 x509 证书上传到 Azure 应用程序清单?

我跟随this post创建了x509证书:

public static X509Certificate2 GenerateSelfSignedCertificate(string subjectName, string issuerName, AsymmetricKeyParameter issuerPrivKey)
{
    const int keyStrength = 2048;

    //generate random numbers
    CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
    SecureRandom random = new SecureRandom(randomGenerator);
    ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerPrivKey, random);

    //the certificate generator
    X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
    certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, true, new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth));

    //serial number
    BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random );
    certificateGenerator.SetSerialNumber(serialNumber);

    // Issuer and Subject Name
    X509Name subjectDN = new X509Name("CN="+ subjectName);
    X509Name issuerDN = new X509Name("CN="+issuerName);
    certificateGenerator.SetIssuerDN(issuerDN);
    certificateGenerator.SetSubjectDN(subjectDN);

    //valid For
    DateTime notBefore = DateTime.Now;
    DateTime notAfter = notBefore.AddYears(2);
    certificateGenerator.SetNotBefore(notBefore);
    certificateGenerator.SetNotAfter(notAfter);

    //Subject Public Key
    AsymmetricCipherKeyPair subjectKeyPair;
    var keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
    var keyPairGenerator = new RsaKeyPairGenerator();
    keyPairGenerator.Init(keyGenerationParameters);
    subjectKeyPair = keyPairGenerator.GenerateKeyPair();

    certificateGenerator.SetPublicKey(subjectKeyPair.Public);

    //selfSign certificate
    Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(signatureFactory);
    var dotNetPrivateKey = ToDotNetKey((RsaPrivateCrtKeyParameters) subjectKeyPair.Private);

    //merge into X509Certificate2
    X509Certificate2 x509 = new X509Certificate2(DotNetUtilities.ToX509Certificate(certificate));
    x509.PrivateKey = dotNetPrivateKey;
    x509.FriendlyName = subjectName;

    return x509;
}


public static X509Certificate2 CreateCertificateAuthorityCertificate(string subjectName, out AsymmetricKeyParameter CaPrivateKey)
{
    const int keyStrength = 2048;

    //generate Random Numbers
    CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
    SecureRandom random = new SecureRandom(randomGenerator);

    //The Certificate Generator
    X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();

    //Serial Number
    BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
    certificateGenerator.SetSerialNumber(serialNumber);

    //Issuer and Subject Name
    X509Name subjectDN = new X509Name("CN="+subjectName);
    X509Name issuerDN = subjectDN;
    certificateGenerator.SetIssuerDN(issuerDN);
    certificateGenerator.SetSubjectDN(subjectDN);

    //valid For
    DateTime notBefore = DateTime.Now;
    DateTime notAfter = notBefore.AddYears(2);

    certificateGenerator.SetNotBefore(notBefore);
    certificateGenerator.SetNotAfter(notAfter);

    //subject Public Key
    AsymmetricCipherKeyPair subjectKeyPair;
    KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
    RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
    keyPairGenerator.Init(keyGenerationParameters);
    subjectKeyPair = keyPairGenerator.GenerateKeyPair();

    certificateGenerator.SetPublicKey(subjectKeyPair.Public);

    //generating the certificate
    AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
    ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA512WITHRSA", issuerKeyPair.Private, random);

    //selfSign Certificate
    Org.BouncyCastle.X509.X509Certificate certificate = certificateGenerator.Generate(signatureFactory);

    X509Certificate2 x509 = new X509Certificate2(certificate.GetEncoded());
    x509.FriendlyName = subjectName;
    CaPrivateKey = issuerKeyPair.Private;

    return x509;
}

public static AsymmetricAlgorithm ToDotNetKey(RsaPrivateCrtKeyParameters privateKey)
{
    var cspParams = new CspParameters()
    {
        KeyContainerName = Guid.NewGuid().ToString(),
        KeyNumber = (int)KeyNumber.Exchange,
        Flags = CspProviderFlags.UseMachineKeyStore
    };

    var rsaProvider = new RSACryptoServiceProvider(cspParams);
    var parameters = new RSAParameters()
    {
        Modulus = privateKey.Modulus.ToByteArrayUnsigned(),
        P = privateKey.P.ToByteArrayUnsigned(),
        Q = privateKey.Q.ToByteArrayUnsigned(),
        DP = privateKey.DP.ToByteArrayUnsigned(),
        DQ = privateKey.DQ.ToByteArrayUnsigned(),
        InverseQ = privateKey.QInv.ToByteArrayUnsigned(),
        D = privateKey.Exponent.ToByteArrayUnsigned(),
        Exponent = privateKey.PublicExponent.ToByteArrayUnsigned()
    };

    rsaProvider.ImportParameters(parameters);

    return rsaProvider;
}

并像这样添加 X509Store:

public static bool addCertToStore(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, System.Security.Cryptography.X509Certificates.StoreName st, System.Security.Cryptography.X509Certificates.StoreLocation sl)
{
    bool bRet = false;

    try
    {
        X509Store store = new X509Store(st, sl);
        store.Open(OpenFlags.ReadWrite);
        store.Add(cert);

        store.Close();
    }
    catch
    {

    }

    return bRet;
}

基本上,我想将我在 Visual Studio 中创建的证书上传到 Azure 门户或 Microsoft 注册门户中的应用程序清单,以获得更强大的访问令牌,用于将事件写入 Outlook 日历。我已经用谷歌搜索了两天,但仍然没有运气......是否有我丢失的文档?

我需要在 Microsoft 注册门户中创建新应用程序时生成的 appSecret 上使用 x509 证书。

谁能指出我正确的方向?

【问题讨论】:

    标签: c# asp.net-mvc azure validation x509certificate


    【解决方案1】:

    有没有办法以编程方式将在 Visual Studios 中创建的 x509 证书上传到 Azure 应用程序清单?

    是的,我们可以使用 Microsoft.Azure.ActiveDirectory.GraphClient 更新 Azure 应用程序主程序。

    我为此做了一个演示。以下是详细步骤,您可以参考:

    如果我们想更新 mainfest keyCredential 我们需要 DELEGATED PERMISSIONS

    1.注册一个azure AD native应用并授予[以登录用户身份访问目录]权限。

    2.创建一个控制台应用程序在Program.cs文件中添加如下代码

     private static async Task<string> GetAppTokenAsync(string graphResourceId, string tenantId, string clientId, string userId)
            {
    
                string aadInstance = "https://login.microsoftonline.com/" + tenantId + "/oauth2/token";
                IPlatformParameters parameters = new PlatformParameters(PromptBehavior.SelectAccount);
                AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance, false);
                var authenticationResult = await authenticationContext.AcquireTokenAsync(graphResourceId, clientId, new Uri("http://localhost"), parameters, new UserIdentifier(userId, UserIdentifierType.UniqueId));
                return authenticationResult.AccessToken;
            }
    
     var graphResourceId = "https://graph.windows.net";
     var tenantId = "tenantId";
     var clientId = "clientId";
     var userId= "313e5ee2-b28exx-xxxx"; Then login user
     var servicePointUri = new Uri(graphResourceId); 
     var serviceRoot = new Uri(servicePointUri, tenantId);
     var activeDirectoryClient = new ActiveDirectoryClient(serviceRoot, async () => await GetAppTokenAsync(graphResourceId, tenantId, clientId, userName));
     var cert = new X509Certificate();
     cert.Import(@"D:\Tom\Documents\tom.cer");// the path fo cert file
     var expirationDate  = DateTime.Parse(cert.GetExpirationDateString()).ToUniversalTime();
     var startDate = DateTime.Parse(cert.GetEffectiveDateString()).ToUniversalTime();
     var binCert =cert.GetRawCertData();
     var keyCredential = new KeyCredential
          {
                    CustomKeyIdentifier = cert.GetCertHash(),
                    EndDate = expirationDate,
                    KeyId = Guid.NewGuid(),
                    StartDate = startDate,
                    Type = "AsymmetricX509Cert",
                    Usage = "Verify",
                    Value = binCert
    
            };
    
       var application = activeDirectoryClient.Applications["ApplicationObjectId"].ExecuteAsync().Result;
       application.KeyCredentials.Add(keyCredential);
       application.UpdateAsync().Wait();
    

    Packages.config

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="Microsoft.Azure.ActiveDirectory.GraphClient" version="2.1.1" targetFramework="net471" />
      <package id="Microsoft.Data.Edm" version="5.6.4" targetFramework="net471" />
      <package id="Microsoft.Data.OData" version="5.6.4" targetFramework="net471" />
      <package id="Microsoft.Data.Services.Client" version="5.6.4" targetFramework="net471" />
      <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.19.8" targetFramework="net471" />
      <package id="System.Spatial" version="5.6.4" targetFramework="net471" />
    </packages>
    

    【讨论】:

    • 谢谢!因为我没有找到任何好的文档,所以我打算从头开始使用这种方法 :)
    • 只有委托权限才能做到这一点?我希望应用程序为每个新租户执行一次。我不想提示用户登录,而是应用程序在后台执行此操作
    • 是的,根据我的测试,只有使用委派权限才有可能。 I don't want to prompt users to log in instead the application does this in the background 如果我有空闲时间,我会研究一下。或者,您可以发布一个新的 SO 线程以从其他社区获得更多帮助。
    • 最坏的情况下,我将使用委派权限进行操作,并提供一次性注册体验,并在此过程中设置“keyCredential”。感谢您的回答,因为现在我的应用程序中需要租户管理员来授予应用程序权限,我使用“grant_type”“client_credentials”来获取访问令牌,但我想让它更安全并使用“grant_type”“ client_assertion" x509 证书解释 here。再次感谢!
    • @Ako 根据我的测试,我们需要使用DELEGATED PERMISSIONS 来更新keyCredential。这意味着我们需要使用用户来获取访问令牌。
    猜你喜欢
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-15
    • 2011-04-15
    相关资源
    最近更新 更多