public static IIdentityServerBuilder AddCaffStoreIdentityServer(this IServiceCollection services, IConfiguration configuration)
        {
            var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents       = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents     = true;
                options.Events.RaiseSuccessEvents     = true;
            })
                          .AddInMemoryIdentityResources(IdentityServerConfig.IdentityResources)
                          .AddInMemoryApiScopes(IdentityServerConfig.ApiScopes)
                          .AddInMemoryClients(IdentityServerConfig.Clients)
                          .AddAspNetIdentity <User>();

            var identityServerOptions = new IdentityServerOptions();

            configuration.Bind(nameof(IdentityServerOptions), identityServerOptions);

            return(identityServerOptions.SigningCredentialSourceType switch
            {
                SigningCredentialSourceType.Developer =>
                builder.AddDeveloperSigningCredential(),

                SigningCredentialSourceType.KeyVault =>
                builder.AddSigningCredential(
                    X509Certificate2Helper.GetCertificateFromAzureKeyVaultAsync(
                        identityServerOptions.AzureKeyVaultUri, identityServerOptions.AzureKeyVaultSigningCertificateName)),

                _ => builder
            });
Пример #2
0
        public static void TestClassSetup(TestContext _)
        {
            // Create a folder to hold the DPS client certificates and X509 self-signed certificates. If a folder by the same name already exists, it will be used.
            s_x509CertificatesFolder = Directory.CreateDirectory($"x509Certificates-{nameof(ProvisioningE2ETests)}-{Guid.NewGuid()}");

            // Extract the public certificate and private key information from the intermediate certificate pfx file.
            // These keys will be used to sign the test leaf device certificates.
            s_intermediateCertificateSubject = X509Certificate2Helper.ExtractPublicCertificateAndPrivateKeyFromPfxAndReturnSubject(
                TestConfiguration.Provisioning.GetGroupEnrollmentIntermediatePfxCertificateBase64(),
                s_certificatePassword,
                s_x509CertificatesFolder);
        }
        private static void AddVaultCertificateStore(this IdentityServerOptions options, VaultCertificateStoreOptions vaultOptions, IVaultAuth vaultAuth)
        {
            // This isn't great but we need a cert at startup
            var client            = new VaultClient(vaultAuth, vaultOptions.VaultUrl, vaultOptions.VaultCertificate);
            var certificateStore  = new VaultCertificateStore(client, vaultOptions.RoleName, vaultOptions.CommonName);
            var certificateHelper = new X509Certificate2Helper();
            var privateKeyHelper  = new RsaCryptoServiceProviderHelper();
            var vaultService      = new VaultCertificateService(options, certificateStore, certificateHelper, privateKeyHelper);

            vaultService.GetCertificates();

            // Register our dependencies
            options.Factory.Register(new Registration <IVaultCertificateService>(vaultService));
            options.Factory.SigningKeyService = new Registration <ISigningKeyService, VaultTokenSigningKeyService>();
        }
Пример #4
0
        private async Task TestInvalidServiceCertificate(ProvisioningTransportHandler transport)
        {
            string certificateSubject = $"E2E_{nameof(ProvisioningCertificateValidationE2ETest)}-{Guid.NewGuid()}";

            X509Certificate2Helper.GenerateSelfSignedCertificateFiles(certificateSubject, s_x509CertificatesFolder, Logger);

            using X509Certificate2 cert = X509Certificate2Helper.CreateX509Certificate2FromPfxFile(certificateSubject, s_x509CertificatesFolder);
            using var security          = new SecurityProviderX509Certificate(cert);
            var provisioningDeviceClient = ProvisioningDeviceClient.Create(
                TestConfiguration.Provisioning.GlobalDeviceEndpointInvalidServiceCertificate,
                "0ne00000001",
                security,
                transport);

            await provisioningDeviceClient.RegisterAsync().ConfigureAwait(false);
        }
        /// <summary>
        /// Creates a new self-signed X509 certificate
        /// </summary>
        /// <param name="issuer">The certificate issuer</param>
        /// <param name="friendlyName">Human readable name</param>
        /// <param name="password">The certificate's password</param>
        /// <param name="startTime">Certificate creation date & time</param>
        /// <param name="endTime">Certificate expiry date & time</param>
        /// <returns>An X509Certificate2</returns>
        public static X509Certificate2 CreateSelfSignedCert(string issuer, string friendlyName, string password, DateTime startTime, DateTime endTime)
        {
            string distinguishedNameString = issuer;
            var    key = Create2048RsaKey();

            var creationParams = new X509CertificateCreationParameters(new X500DistinguishedName(distinguishedNameString))
            {
                TakeOwnershipOfKey = true,
                StartTime          = startTime,
                EndTime            = endTime
            };

            // adding client authentication, -eku = 1.3.6.1.5.5.7.3.2,
            // This is mandatory for the upload to be successful
            OidCollection oidCollection = new OidCollection();

            oidCollection.Add(new Oid(OIDClientAuthValue, OIDClientAuthFriendlyName));
            creationParams.Extensions.Add(new X509EnhancedKeyUsageExtension(oidCollection, false));

            // Documentation of CreateSelfSignedCertificate states:
            // If creationParameters have TakeOwnershipOfKey set to true, the certificate
            // generated will own the key and the input CngKey will be disposed to ensure
            // that the caller doesn't accidentally use it beyond its lifetime (which is
            // now controlled by the certificate object).
            // We don't dispose it ourselves in this case.
            var cert = key.CreateSelfSignedCertificate(creationParams);

            key = null;
            cert.FriendlyName = friendlyName;

            // X509 certificate needs PersistKeySet flag set.
            // Reload a new X509Certificate2 instance from exported bytes in order to set the PersistKeySet flag.
            var bytes = cert.Export(X509ContentType.Pfx, password);

            // NOTE: PfxValidation is not done here because these are newly created certs and assumed valid.

            ICommonEventSource evtSource = null;

            return(X509Certificate2Helper.NewX509Certificate2(bytes, password, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable, evtSource, doPfxValidation: false));
        }
Пример #6
0
        private async Task<SecurityProvider> CreateSecurityProviderFromNameAsync(
            AttestationMechanismType attestationType,
            EnrollmentType? enrollmentType,
            string groupId,
            ReprovisionPolicy reprovisionPolicy,
            AllocationPolicy allocationPolicy,
            CustomAllocationDefinition customAllocationDefinition,
            ICollection<string> iothubs,
            DeviceCapabilities capabilities = null)
        {
            _verboseLog.WriteLine($"{nameof(CreateSecurityProviderFromNameAsync)}({attestationType})");

            string registrationId = AttestationTypeToString(attestationType) + "-" + Guid.NewGuid();
            using var provisioningServiceClient = ProvisioningServiceClient.CreateFromConnectionString(TestConfiguration.Provisioning.ConnectionString);

            switch (attestationType)
            {
                case AttestationMechanismType.Tpm:
                    IndividualEnrollment tpmEnrollment = await CreateIndividualEnrollmentAsync(
                        provisioningServiceClient,
                        registrationId,
                        AttestationMechanismType.Tpm,
                        null,
                        reprovisionPolicy,
                        allocationPolicy,
                        customAllocationDefinition,
                        iothubs,
                        capabilities,
                        Logger).ConfigureAwait(false);

                    return new SecurityProviderTpmSimulator(tpmEnrollment.RegistrationId);

                case AttestationMechanismType.X509:
                    X509Certificate2 certificate = null;
                    X509Certificate2Collection collection = null;
                    switch (enrollmentType)
                    {
                        case EnrollmentType.Individual:
                            X509Certificate2Helper.GenerateSelfSignedCertificateFiles(registrationId, s_x509CertificatesFolder, Logger);

#pragma warning disable CA2000 // Dispose objects before losing scope
                            // This certificate is used for authentication with IoT hub and is returned to the caller of this method.
                            // It is disposed when the caller to this method is disposed, at the end of the test method.
                            certificate = X509Certificate2Helper.CreateX509Certificate2FromPfxFile(registrationId, s_x509CertificatesFolder);
#pragma warning restore CA2000 // Dispose objects before losing scope

                            using (X509Certificate2 publicCertificate = X509Certificate2Helper.CreateX509Certificate2FromCerFile(registrationId, s_x509CertificatesFolder))
                            {
                                IndividualEnrollment x509IndividualEnrollment = await CreateIndividualEnrollmentAsync(
                                    provisioningServiceClient,
                                    registrationId,
                                    AttestationMechanismType.X509,
                                    publicCertificate,
                                    reprovisionPolicy,
                                    allocationPolicy,
                                    customAllocationDefinition,
                                    iothubs,
                                    capabilities,
                                    Logger).ConfigureAwait(false);

                                x509IndividualEnrollment.Attestation.Should().BeAssignableTo<X509Attestation>();
                            }

                            break;

                        case EnrollmentType.Group:
                            // The X509 enrollment group has been hardcoded for the purpose of E2E tests and the root certificate has been verified on DPS.
                            // Each device identity provisioning through the above enrollment group is created on-demand.

                            X509Certificate2Helper.GenerateIntermediateCertificateSignedCertificateFiles(
                                registrationId,
                                s_intermediateCertificateSubject,
                                s_x509CertificatesFolder,
                                Logger);

#pragma warning disable CA2000 // Dispose objects before losing scope
                            // This certificate is used for authentication with IoT hub and is returned to the caller of this method.
                            // It is disposed when the caller to this method is disposed, at the end of the test method.
                            certificate = X509Certificate2Helper.CreateX509Certificate2FromPfxFile(registrationId, s_x509CertificatesFolder);
#pragma warning restore CA2000 // Dispose objects before losing scope

                            collection = new X509Certificate2Collection
                            {
                                TestConfiguration.CommonCertificates.GetRootCaCertificate(),
                                TestConfiguration.CommonCertificates.GetIntermediate1Certificate(),
                                TestConfiguration.CommonCertificates.GetIntermediate2Certificate(),
                                X509Certificate2Helper.CreateX509Certificate2FromCerFile(registrationId, s_x509CertificatesFolder)
                            };
                            break;

                        default:
                            throw new NotSupportedException($"Unknown X509 type: '{enrollmentType}'");
                    }

                    return new SecurityProviderX509Certificate(certificate, collection);

                case AttestationMechanismType.SymmetricKey:
                    switch (enrollmentType)
                    {
                        case EnrollmentType.Group:
                            EnrollmentGroup symmetricKeyEnrollmentGroup = await CreateEnrollmentGroupAsync(
                                    provisioningServiceClient,
                                    AttestationMechanismType.SymmetricKey,
                                    groupId,
                                    reprovisionPolicy,
                                    allocationPolicy,
                                    customAllocationDefinition,
                                    iothubs,
                                    capabilities,
                                    Logger)
                                .ConfigureAwait(false);
                            Assert.IsTrue(symmetricKeyEnrollmentGroup.Attestation is SymmetricKeyAttestation);
                            var symmetricKeyAttestation = (SymmetricKeyAttestation)symmetricKeyEnrollmentGroup.Attestation;
                            string registrationIdSymmetricKey = _idPrefix + Guid.NewGuid();
                            string primaryKeyEnrollmentGroup = symmetricKeyAttestation.PrimaryKey;
                            string secondaryKeyEnrollmentGroup = symmetricKeyAttestation.SecondaryKey;

                            string primaryKeyIndividual = ComputeDerivedSymmetricKey(Convert.FromBase64String(primaryKeyEnrollmentGroup), registrationIdSymmetricKey);
                            string secondaryKeyIndividual = ComputeDerivedSymmetricKey(Convert.FromBase64String(secondaryKeyEnrollmentGroup), registrationIdSymmetricKey);

                            return new SecurityProviderSymmetricKey(registrationIdSymmetricKey, primaryKeyIndividual, secondaryKeyIndividual);

                        case EnrollmentType.Individual:
                            IndividualEnrollment symmetricKeyEnrollment = await CreateIndividualEnrollmentAsync(
                                provisioningServiceClient,
                                registrationId,
                                AttestationMechanismType.SymmetricKey,
                                null,
                                reprovisionPolicy,
                                allocationPolicy,
                                customAllocationDefinition,
                                iothubs,
                                capabilities,
                                Logger).ConfigureAwait(false);

                            Assert.IsTrue(symmetricKeyEnrollment.Attestation is SymmetricKeyAttestation);
                            symmetricKeyAttestation = (SymmetricKeyAttestation)symmetricKeyEnrollment.Attestation;

                            registrationIdSymmetricKey = symmetricKeyEnrollment.RegistrationId;
                            string primaryKey = symmetricKeyAttestation.PrimaryKey;
                            string secondaryKey = symmetricKeyAttestation.SecondaryKey;
                            return new SecurityProviderSymmetricKey(registrationIdSymmetricKey, primaryKey, secondaryKey);

                        default:
                            throw new NotSupportedException("Unrecognized enrollment type");
                    }
                default:
                    throw new NotSupportedException("Unrecognized attestation type");
            }

            throw new NotSupportedException($"Unknown security type: '{attestationType}'.");
        }