diff --git a/privateca/snippets/README.md b/privateca/snippets/README.md new file mode 100644 index 00000000000..5587b341ed2 --- /dev/null +++ b/privateca/snippets/README.md @@ -0,0 +1,75 @@ +# Google Cloud Private Certificate Authority Service + + +Open in Cloud Shell + +Google [Cloud Private Certificate Authority Service](https://cloud.google.com/certificate-authority-service) is a highly available, scalable Google Cloud service that enables you to simplify, automate, and customize the deployment, management, and security of private certificate authorities (CA). + +These sample Java applications demonstrate how to access the Cloud CA API using the +Google Java API Client Libraries. + +## Prerequisites + +### Google Cloud Project + +Set up a Google Cloud project with billing enabled. + +### Enable the API + +You must [enable the Google Private Certificate Authority Service API](https://console.cloud.google.com/flows/enableapi?apiid=privateca.googleapis.com) for your project in order to use these samples. + +### Service account + +A service account with private key credentials is required to create signed bearer tokens. +Create a [service account](https://console.cloud.google.com/iam-admin/serviceaccounts/create) and download the credentials file as JSON. + +### Set Environment Variables + +You must set your project ID and service account credentials in order to run the tests. + +``` +$ export GOOGLE_CLOUD_PROJECT="" +$ export GOOGLE_APPLICATION_CREDENTIALS="" +``` + +### Grant Permissions + +You must ensure that the [user account or service account](https://cloud.google.com/iam/docs/service-accounts#differences_between_a_service_account_and_a_user_account) you used to authorize your gcloud session has the proper permissions to edit Private CA resources for your project. In the Cloud Console under IAM, add the following roles to the project whose service account you're using to test: + +* Cloud CA Service Admin +* Cloud CA Service Certificate Requester +* Cloud CA Service Certificate Manager +* Cloud CA Service Certificate Template User +* Cloud CA Service Workload Certificate Requester +* Cloud CA Service Operation Manager +* Cloud CA Service Auditor + +More information can be found in the [Google Private Certificate Authority Service Docs](https://cloud.google.com/certificate-authority-service/docs/reference/permissions-and-roles). + + +## Build and Run + +The following instructions will help you prepare your development environment. + +1. Download and install the [Java Development Kit (JDK)](https://www.oracle.com/java/technologies/javase-downloads.html). + Verify that the [JAVA_HOME](https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/envvars001.html) environment variable is set and points to your JDK installation. + + +2. Download and install [Apache Maven](http://maven.apache.org/download.cgi) by following the [Maven installation guide](http://maven.apache.org/install.html) for your specific operating system. + + +3. Clone the GoogleCloudPlatform/java-docs-samples repository. +``` +git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git +``` + +4. Navigate to the sample code directory. + +``` +cd privateca/snippets +``` + +5. Run the **SnippetsIT** test file present under the test folder. + +### Crypto frameworks +[Bouncy Castle](https://www.bouncycastle.org/documentation.html) cryptographic framework is used as a part of testing. diff --git a/privateca/snippets/pom.xml b/privateca/snippets/pom.xml new file mode 100644 index 00000000000..884193b3d83 --- /dev/null +++ b/privateca/snippets/pom.xml @@ -0,0 +1,84 @@ + + + + 4.0.0 + com.google.cloud + security-private-ca-snippets + jar + Google Certificate Authority Service Snippets + https://github.com/GoogleCloudPlatform/java-docs-samples + + + + com.google.cloud.samples + shared-configuration + 1.2.0 + + + + 1.8 + 1.8 + UTF-8 + + + + + + com.google.cloud + libraries-bom + 26.1.3 + pom + import + + + + + + + + com.google.cloud + google-cloud-security-private-ca + 2.5.4 + + + org.bouncycastle + bcpkix-jdk15on + 1.70 + + + com.google.cloud + google-cloud-kms + + + com.google.cloud + google-cloud-monitoring + + + + junit + junit + 4.13.2 + test + + + com.google.truth + truth + 1.1.3 + test + + + diff --git a/privateca/snippets/src/main/java/privateca/ActivateSubordinateCa.java b/privateca/snippets/src/main/java/privateca/ActivateSubordinateCa.java new file mode 100644 index 00000000000..e233df5ee85 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/ActivateSubordinateCa.java @@ -0,0 +1,134 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_activate_subordinateca] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.ActivateCertificateAuthorityRequest; +import com.google.cloud.security.privateca.v1.CertificateAuthorityName; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.SubordinateConfig; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +public class ActivateSubordinateCa { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, IOException { + // TODO(developer): Replace these variables before running the sample. + + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Set a unique id for the CA pool. + // subordinateCaName: The CA to be activated. + // pemCaCertificate: The signed certificate, obtained by signing the CSR. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String subordinateCaName = "subordinate-certificate-authority-name"; + String pemCaCertificate = + "-----BEGIN CERTIFICATE-----\n" + "sample-pem-certificate\n" + "-----END CERTIFICATE-----"; + + // certificateAuthorityName: The name of the certificate authority which signed the CSR. + // If an external CA (CA not present in Google Cloud) was used for signing, + // then use the CA's issuerCertificateChain. + String certificateAuthorityName = "certificate-authority-name"; + + activateSubordinateCa( + project, location, poolId, certificateAuthorityName, subordinateCaName, pemCaCertificate); + } + + // Activate a subordinate CA. + // *Prerequisite*: Get the CSR of the subordinate CA signed by another CA. Pass in the signed + // certificate and (issuer CA's name or the issuer CA's Certificate chain). + // *Post*: After activating the subordinate CA, it should be enabled before issuing certificates. + public static void activateSubordinateCa( + String project, + String location, + String poolId, + String certificateAuthorityName, + String subordinateCaName, + String pemCaCertificate) + throws ExecutionException, InterruptedException, IOException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + // Subordinate CA parent. + String subordinateCaParent = + CertificateAuthorityName.of(project, location, poolId, subordinateCaName).toString(); + + // Construct the "Activate CA Request". + ActivateCertificateAuthorityRequest activateCertificateAuthorityRequest = + ActivateCertificateAuthorityRequest.newBuilder() + .setName(subordinateCaParent) + // The signed certificate. + .setPemCaCertificate(pemCaCertificate) + .setSubordinateConfig( + SubordinateConfig.newBuilder() + // Follow one of the below methods: + + // Method 1: If issuer CA is in Google Cloud, set the Certificate Authority + // Name. + .setCertificateAuthority( + CertificateAuthorityName.of( + project, location, poolId, certificateAuthorityName) + .toString()) + + // Method 2: If issuer CA is external to Google Cloud, set the issuer's + // certificate chain. + // The certificate chain of the CA (which signed the CSR) from leaf to root. + // .setPemIssuerChain( + // SubordinateConfigChain.newBuilder() + // .addAllPemCertificates(issuerCertificateChain) + // .build()) + + .build()) + .build(); + + // Activate the CA. + ApiFuture futureCall = + certificateAuthorityServiceClient + .activateCertificateAuthorityCallable() + .futureCall(activateCertificateAuthorityRequest); + + Operation response = futureCall.get(); + + if (response.hasError()) { + System.out.println("Error while activating the subordinate CA! " + response.getError()); + return; + } + + System.out.println( + "Subordinate Certificate Authority activated successfully ! !" + subordinateCaName); + TimeUnit.SECONDS.sleep(3); + // The current state will be STAGED. + // The Subordinate CA has to be ENABLED before issuing certificates. + System.out.println( + "Current State: " + + certificateAuthorityServiceClient + .getCertificateAuthority(subordinateCaParent) + .getState()); + } + } +} +// [END privateca_activate_subordinateca] diff --git a/privateca/snippets/src/main/java/privateca/CreateCaPool.java b/privateca/snippets/src/main/java/privateca/CreateCaPool.java new file mode 100644 index 00000000000..044bb67ad42 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/CreateCaPool.java @@ -0,0 +1,94 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_create_ca_pool] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CaPool; +import com.google.cloud.security.privateca.v1.CaPool.IssuancePolicy; +import com.google.cloud.security.privateca.v1.CaPool.Tier; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateIdentityConstraints; +import com.google.cloud.security.privateca.v1.CreateCaPoolRequest; +import com.google.cloud.security.privateca.v1.LocationName; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class CreateCaPool { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Set a unique poolId for the CA pool. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + createCaPool(project, location, poolId); + } + + // Create a Certificate Authority Pool. All certificates created under this CA pool will + // follow the same issuance policy, IAM policies,etc., + public static void createCaPool(String project, String location, String poolId) + throws InterruptedException, ExecutionException, IOException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + IssuancePolicy issuancePolicy = IssuancePolicy.newBuilder() + .setIdentityConstraints(CertificateIdentityConstraints.newBuilder() + .setAllowSubjectPassthrough(true) + .setAllowSubjectAltNamesPassthrough(true) + .build()) + .build(); + + /* Create the pool request + Set Parent which denotes the project id and location. + Set the Tier (see: https://cloud.google.com/certificate-authority-service/docs/tiers). + */ + CreateCaPoolRequest caPoolRequest = + CreateCaPoolRequest.newBuilder() + .setParent(LocationName.of(project, location).toString()) + .setCaPoolId(poolId) + .setCaPool( + CaPool.newBuilder() + .setIssuancePolicy(issuancePolicy) + .setTier(Tier.ENTERPRISE) + .build()) + .build(); + + // Create the CA pool. + ApiFuture futureCall = + certificateAuthorityServiceClient.createCaPoolCallable().futureCall(caPoolRequest); + Operation response = futureCall.get(); + + if (response.hasError()) { + System.out.println("Error while creating CA pool !" + response.getError()); + return; + } + + System.out.println("CA pool created successfully: " + poolId); + } + } +} +// [END privateca_create_ca_pool] diff --git a/privateca/snippets/src/main/java/privateca/CreateCertificate.java b/privateca/snippets/src/main/java/privateca/CreateCertificate.java new file mode 100644 index 00000000000..77089aeac7a --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/CreateCertificate.java @@ -0,0 +1,157 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_create_certificate] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.Certificate; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateConfig; +import com.google.cloud.security.privateca.v1.CertificateConfig.SubjectConfig; +import com.google.cloud.security.privateca.v1.CreateCertificateRequest; +import com.google.cloud.security.privateca.v1.KeyUsage; +import com.google.cloud.security.privateca.v1.KeyUsage.ExtendedKeyUsageOptions; +import com.google.cloud.security.privateca.v1.KeyUsage.KeyUsageOptions; +import com.google.cloud.security.privateca.v1.PublicKey; +import com.google.cloud.security.privateca.v1.PublicKey.KeyFormat; +import com.google.cloud.security.privateca.v1.Subject; +import com.google.cloud.security.privateca.v1.SubjectAltNames; +import com.google.cloud.security.privateca.v1.X509Parameters; +import com.google.cloud.security.privateca.v1.X509Parameters.CaOptions; +import com.google.protobuf.ByteString; +import com.google.protobuf.Duration; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class CreateCertificate { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, IOException { + // TODO(developer): Replace these variables before running the sample. + + // publicKeyBytes: Public key used in signing the certificates. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Set a unique id for the CA pool. + // certificateAuthorityName: The name of the certificate authority which issues the certificate. + // certificateName: Set a unique name for the certificate. + String project = "your-project-id"; + ByteString publicKeyBytes = ByteString.copyFrom(new byte[]{}); + String location = "ca-location"; + String poolId = "ca-poolId"; + String certificateAuthorityName = "certificate-authority-name"; + String certificateName = "certificate-name"; + + createCertificate( + project, location, poolId, certificateAuthorityName, certificateName, publicKeyBytes); + } + + // Create a Certificate which is issued by the Certificate Authority present in the CA Pool. + // The public key used to sign the certificate can be generated using any crypto + // library/framework. + public static void createCertificate( + String project, + String location, + String poolId, + String certificateAuthorityName, + String certificateName, + ByteString publicKeyBytes) + throws InterruptedException, ExecutionException, IOException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + // commonName: Enter a title for your certificate. + // orgName: Provide the name of your company. + // domainName: List the fully qualified domain name. + // certificateLifetime: The validity of the certificate in seconds. + String commonName = "commonname"; + String orgName = "orgname"; + String domainName = "dns.example.com"; + long certificateLifetime = 1000L; + + // Set the Public Key and its format. + PublicKey publicKey = + PublicKey.newBuilder().setKey(publicKeyBytes).setFormat(KeyFormat.PEM).build(); + + SubjectConfig subjectConfig = + SubjectConfig.newBuilder() + // Set the common name and org name. + .setSubject( + Subject.newBuilder().setCommonName(commonName).setOrganization(orgName).build()) + // Set the fully qualified domain name. + .setSubjectAltName(SubjectAltNames.newBuilder().addDnsNames(domainName).build()) + .build(); + + // Set the X.509 fields required for the certificate. + X509Parameters x509Parameters = + X509Parameters.newBuilder() + .setKeyUsage( + KeyUsage.newBuilder() + .setBaseKeyUsage( + KeyUsageOptions.newBuilder() + .setDigitalSignature(true) + .setKeyEncipherment(true) + .setCertSign(true) + .build()) + .setExtendedKeyUsage( + ExtendedKeyUsageOptions.newBuilder().setServerAuth(true).build()) + .build()) + .setCaOptions(CaOptions.newBuilder().setIsCa(true).buildPartial()) + .build(); + + // Create certificate. + Certificate certificate = + Certificate.newBuilder() + .setConfig( + CertificateConfig.newBuilder() + .setPublicKey(publicKey) + .setSubjectConfig(subjectConfig) + .setX509Config(x509Parameters) + .build()) + .setLifetime(Duration.newBuilder().setSeconds(certificateLifetime).build()) + .build(); + + // Create the Certificate Request. + CreateCertificateRequest certificateRequest = + CreateCertificateRequest.newBuilder() + .setParent(CaPoolName.of(project, location, poolId).toString()) + .setCertificateId(certificateName) + .setCertificate(certificate) + .setIssuingCertificateAuthorityId(certificateAuthorityName) + .build(); + + // Get the Certificate response. + ApiFuture future = + certificateAuthorityServiceClient + .createCertificateCallable() + .futureCall(certificateRequest); + + Certificate response = future.get(); + // Get the PEM encoded, signed X.509 certificate. + System.out.println(response.getPemCertificate()); + // To verify the obtained certificate, use this intermediate chain list. + System.out.println(response.getPemCertificateChainList()); + } + } +} +// [END privateca_create_certificate] diff --git a/privateca/snippets/src/main/java/privateca/CreateCertificateAuthority.java b/privateca/snippets/src/main/java/privateca/CreateCertificateAuthority.java new file mode 100644 index 00000000000..09f486d1a8d --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/CreateCertificateAuthority.java @@ -0,0 +1,133 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_create_ca] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.CertificateAuthority; +import com.google.cloud.security.privateca.v1.CertificateAuthority.KeyVersionSpec; +import com.google.cloud.security.privateca.v1.CertificateAuthority.SignHashAlgorithm; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateConfig; +import com.google.cloud.security.privateca.v1.CertificateConfig.SubjectConfig; +import com.google.cloud.security.privateca.v1.CreateCertificateAuthorityRequest; +import com.google.cloud.security.privateca.v1.KeyUsage; +import com.google.cloud.security.privateca.v1.KeyUsage.KeyUsageOptions; +import com.google.cloud.security.privateca.v1.Subject; +import com.google.cloud.security.privateca.v1.X509Parameters; +import com.google.cloud.security.privateca.v1.X509Parameters.CaOptions; +import com.google.longrunning.Operation; +import com.google.protobuf.Duration; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class CreateCertificateAuthority { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Set it to the CA Pool under which the CA should be created. + // certificateAuthorityName: Unique name for the CA. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String certificateAuthorityName = "certificate-authority-name"; + createCertificateAuthority(project, location, poolId, certificateAuthorityName); + } + + // Create Certificate Authority which is the root CA in the given CA Pool. + public static void createCertificateAuthority( + String project, String location, String poolId, String certificateAuthorityName) + throws InterruptedException, ExecutionException, IOException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + String commonName = "common-name"; + String orgName = "org-name"; + int caDuration = 100000; // Validity of this CA in seconds. + + // Set the type of Algorithm. + KeyVersionSpec keyVersionSpec = + KeyVersionSpec.newBuilder().setAlgorithm(SignHashAlgorithm.RSA_PKCS1_4096_SHA256).build(); + + // Set CA subject config. + SubjectConfig subjectConfig = + SubjectConfig.newBuilder() + .setSubject( + Subject.newBuilder().setCommonName(commonName).setOrganization(orgName).build()) + .build(); + + // Set the key usage options for X.509 fields. + X509Parameters x509Parameters = + X509Parameters.newBuilder() + .setKeyUsage( + KeyUsage.newBuilder() + .setBaseKeyUsage( + KeyUsageOptions.newBuilder().setCrlSign(true).setCertSign(true).build()) + .build()) + .setCaOptions(CaOptions.newBuilder().setIsCa(true).build()) + .build(); + + // Set certificate authority settings. + CertificateAuthority certificateAuthority = + CertificateAuthority.newBuilder() + // CertificateAuthority.Type.SELF_SIGNED denotes that this CA is a root CA. + .setType(CertificateAuthority.Type.SELF_SIGNED) + .setKeySpec(keyVersionSpec) + .setConfig( + CertificateConfig.newBuilder() + .setSubjectConfig(subjectConfig) + .setX509Config(x509Parameters) + .build()) + // Set the CA validity duration. + .setLifetime(Duration.newBuilder().setSeconds(caDuration).build()) + .build(); + + // Create the CertificateAuthorityRequest. + CreateCertificateAuthorityRequest certificateAuthorityRequest = + CreateCertificateAuthorityRequest.newBuilder() + .setParent(CaPoolName.of(project, location, poolId).toString()) + .setCertificateAuthorityId(certificateAuthorityName) + .setCertificateAuthority(certificateAuthority) + .build(); + + // Create Certificate Authority. + ApiFuture futureCall = + certificateAuthorityServiceClient + .createCertificateAuthorityCallable() + .futureCall(certificateAuthorityRequest); + Operation response = futureCall.get(); + + if (response.hasError()) { + System.out.println("Error while creating CA !" + response.getError()); + return; + } + + System.out.println( + "Certificate Authority created successfully : " + certificateAuthorityName); + } + } +} +// [END privateca_create_ca] diff --git a/privateca/snippets/src/main/java/privateca/CreateCertificateCsr.java b/privateca/snippets/src/main/java/privateca/CreateCertificateCsr.java new file mode 100644 index 00000000000..8d98ac05f2b --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/CreateCertificateCsr.java @@ -0,0 +1,109 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_create_certificate_csr] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.Certificate; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CreateCertificateRequest; +import com.google.protobuf.Duration; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class CreateCertificateCsr { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException { + // TODO(developer): Replace these variables before running the sample. + + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Set a unique id for the CA pool. + // certificateAuthorityName: The name of the certificate authority to sign the CSR. + // certificateName: Set a unique name for the certificate. + // pemCsr: Set the Certificate Issuing Request in the pem encoded format. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String certificateAuthorityName = "certificate-authority-name"; + String certificateName = "certificate-name"; + String pemCsr = + "-----BEGIN CERTIFICATE REQUEST-----\n" + + "sample-pem-csr-format\n" + + "-----END CERTIFICATE REQUEST-----"; + + createCertificateWithCsr( + project, location, poolId, certificateAuthorityName, certificateName, pemCsr); + } + + // Create a Certificate which is issued by the specified Certificate Authority. + // The certificate details and the public key is provided as a CSR (Certificate Signing Request). + public static void createCertificateWithCsr( + String project, + String location, + String poolId, + String certificateAuthorityName, + String certificateName, + String pemCsr) + throws IOException, ExecutionException, InterruptedException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + // certificateLifetime: The validity of the certificate in seconds. + long certificateLifetime = 1000L; + + // Create certificate with CSR. + // The pemCSR contains the public key and the domain details required. + Certificate certificate = + Certificate.newBuilder() + .setPemCsr(pemCsr) + .setLifetime(Duration.newBuilder().setSeconds(certificateLifetime).build()) + .build(); + + // Create the Certificate Request. + // Set the CA which is responsible for creating the certificate with the provided CSR. + CreateCertificateRequest certificateRequest = + CreateCertificateRequest.newBuilder() + .setParent(CaPoolName.of(project, location, poolId).toString()) + .setIssuingCertificateAuthorityId(certificateAuthorityName) + .setCertificateId(certificateName) + .setCertificate(certificate) + .build(); + + // Get the certificate response. + ApiFuture future = + certificateAuthorityServiceClient + .createCertificateCallable() + .futureCall(certificateRequest); + + Certificate certificateResponse = future.get(); + + System.out.println("Certificate created successfully : " + certificateResponse.getName()); + + // Get the signed certificate and the issuer chain list. + System.out.println("Signed certificate:\n " + certificateResponse.getPemCertificate()); + System.out.println("Issuer chain list:\n" + certificateResponse.getPemCertificateChainList()); + } + } +} +// [END privateca_create_certificate_csr] diff --git a/privateca/snippets/src/main/java/privateca/CreateCertificateTemplate.java b/privateca/snippets/src/main/java/privateca/CreateCertificateTemplate.java new file mode 100644 index 00000000000..8390e3c111e --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/CreateCertificateTemplate.java @@ -0,0 +1,122 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_create_certificate_template] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateIdentityConstraints; +import com.google.cloud.security.privateca.v1.CertificateTemplate; +import com.google.cloud.security.privateca.v1.CreateCertificateTemplateRequest; +import com.google.cloud.security.privateca.v1.KeyUsage; +import com.google.cloud.security.privateca.v1.KeyUsage.ExtendedKeyUsageOptions; +import com.google.cloud.security.privateca.v1.KeyUsage.KeyUsageOptions; +import com.google.cloud.security.privateca.v1.LocationName; +import com.google.cloud.security.privateca.v1.X509Parameters; +import com.google.cloud.security.privateca.v1.X509Parameters.CaOptions; +import com.google.longrunning.Operation; +import com.google.type.Expr; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class CreateCertificateTemplate { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + /* TODO(developer): Replace these variables before running the sample. + location: For a list of locations, see: + https://cloud.google.com/certificate-authority-service/docs/locations */ + String project = "your-project-id"; + String location = "ca-location"; + String certificateTemplateId = "certificate-template-id"; + + createCertificateTemplate(project, location, certificateTemplateId); + } + + /* Creates a Certificate template. These templates can be reused for common + certificate issuance scenarios. */ + public static void createCertificateTemplate( + String project, String location, String certificateTemplateId) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + /* Initialize client that will be used to send requests. This client only needs to be created + once, and can be reused for multiple requests. After completing all of your requests, call + the `certificateAuthorityServiceClient.close()` method on the client to safely + clean up any remaining background resources. */ + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + /* Describes any predefined X.509 values set by this template. + The provided extensions are copied over to certificate requests that use this template.*/ + KeyUsage keyUsage = + KeyUsage.newBuilder() + .setBaseKeyUsage( + KeyUsageOptions.newBuilder() + .setDigitalSignature(true) + .setKeyEncipherment(true) + .build()) + .setExtendedKeyUsage(ExtendedKeyUsageOptions.newBuilder().setServerAuth(true).build()) + .build(); + + CaOptions caOptions = CaOptions.newBuilder().setIsCa(false).build(); + + /* CEL expression that is evaluated against the Subject and + Subject Alternative Name of the certificate before it is issued. */ + Expr expr = + Expr.newBuilder().setExpression("subject_alt_names.all(san, san.type == DNS)").build(); + + // Set the certificate issuance schema. + CertificateTemplate certificateTemplate = + CertificateTemplate.newBuilder() + .setPredefinedValues( + X509Parameters.newBuilder().setKeyUsage(keyUsage).setCaOptions(caOptions).build()) + .setIdentityConstraints( + CertificateIdentityConstraints.newBuilder() + .setCelExpression(expr) + .setAllowSubjectPassthrough(false) + .setAllowSubjectAltNamesPassthrough(false) + .build()) + .build(); + + // Set the parent and certificate template properties. + CreateCertificateTemplateRequest certificateTemplateRequest = + CreateCertificateTemplateRequest.newBuilder() + .setParent(LocationName.of(project, location).toString()) + .setCertificateTemplate(certificateTemplate) + .setCertificateTemplateId(certificateTemplateId) + .build(); + + // Create Template request. + ApiFuture futureCall = + certificateAuthorityServiceClient + .createCertificateTemplateCallable() + .futureCall(certificateTemplateRequest); + + Operation response = futureCall.get(60, TimeUnit.SECONDS); + + if (response.hasError()) { + System.out.println("Error creating certificate template ! " + response.getError()); + return; + } + + System.out.println("Successfully created certificate template ! " + response.getName()); + } + } +} +// [END privateca_create_certificate_template] diff --git a/privateca/snippets/src/main/java/privateca/CreateSubordinateCa.java b/privateca/snippets/src/main/java/privateca/CreateSubordinateCa.java new file mode 100644 index 00000000000..cde09b7efb6 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/CreateSubordinateCa.java @@ -0,0 +1,137 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_create_subordinateca] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.CertificateAuthority; +import com.google.cloud.security.privateca.v1.CertificateAuthority.KeyVersionSpec; +import com.google.cloud.security.privateca.v1.CertificateAuthority.SignHashAlgorithm; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateConfig; +import com.google.cloud.security.privateca.v1.CertificateConfig.SubjectConfig; +import com.google.cloud.security.privateca.v1.CreateCertificateAuthorityRequest; +import com.google.cloud.security.privateca.v1.KeyUsage; +import com.google.cloud.security.privateca.v1.KeyUsage.KeyUsageOptions; +import com.google.cloud.security.privateca.v1.Subject; +import com.google.cloud.security.privateca.v1.SubjectAltNames; +import com.google.cloud.security.privateca.v1.X509Parameters; +import com.google.cloud.security.privateca.v1.X509Parameters.CaOptions; +import com.google.longrunning.Operation; +import com.google.protobuf.Duration; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class CreateSubordinateCa { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Set it to the CA Pool under which the CA should be created. + // subordinateCaName: Unique name for the Subordinate CA. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String subordinateCaName = "subordinate-certificate-authority-name"; + + createSubordinateCertificateAuthority(project, location, poolId, subordinateCaName); + } + + public static void createSubordinateCertificateAuthority( + String project, String location, String poolId, String subordinateCaName) + throws IOException, ExecutionException, InterruptedException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + String commonName = "commonname"; + String orgName = "csr-org-name"; + String domainName = "dns.example.com"; + int caDuration = 100000; // Validity of this CA in seconds. + + // Set the type of Algorithm. + KeyVersionSpec keyVersionSpec = + KeyVersionSpec.newBuilder().setAlgorithm(SignHashAlgorithm.RSA_PKCS1_4096_SHA256).build(); + + // Set CA subject config. + SubjectConfig subjectConfig = + SubjectConfig.newBuilder() + .setSubject( + Subject.newBuilder().setCommonName(commonName).setOrganization(orgName).build()) + // Set the fully qualified domain name. + .setSubjectAltName(SubjectAltNames.newBuilder().addDnsNames(domainName).build()) + .build(); + + // Set the key usage options for X.509 fields. + X509Parameters x509Parameters = + X509Parameters.newBuilder() + .setKeyUsage( + KeyUsage.newBuilder() + .setBaseKeyUsage( + KeyUsageOptions.newBuilder().setCrlSign(true).setCertSign(true).build()) + .build()) + .setCaOptions(CaOptions.newBuilder().setIsCa(true).build()) + .build(); + + // Set certificate authority settings. + CertificateAuthority subCertificateAuthority = + CertificateAuthority.newBuilder() + .setType(CertificateAuthority.Type.SUBORDINATE) + .setKeySpec(keyVersionSpec) + .setConfig( + CertificateConfig.newBuilder() + .setSubjectConfig(subjectConfig) + .setX509Config(x509Parameters) + .build()) + // Set the CA validity duration. + .setLifetime(Duration.newBuilder().setSeconds(caDuration).build()) + .build(); + + // Create the CertificateAuthorityRequest. + CreateCertificateAuthorityRequest subCertificateAuthorityRequest = + CreateCertificateAuthorityRequest.newBuilder() + .setParent(CaPoolName.of(project, location, poolId).toString()) + .setCertificateAuthorityId(subordinateCaName) + .setCertificateAuthority(subCertificateAuthority) + .build(); + + // Create Subordinate CA. + ApiFuture futureCall = + certificateAuthorityServiceClient + .createCertificateAuthorityCallable() + .futureCall(subCertificateAuthorityRequest); + + Operation response = futureCall.get(); + + if (response.hasError()) { + System.out.println("Error while creating Subordinate CA !" + response.getError()); + return; + } + + System.out.println( + "Subordinate Certificate Authority created successfully : " + subordinateCaName); + } + } +} +// [END privateca_create_subordinateca] diff --git a/privateca/snippets/src/main/java/privateca/DeleteCaPool.java b/privateca/snippets/src/main/java/privateca/DeleteCaPool.java new file mode 100644 index 00000000000..1745469136c --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/DeleteCaPool.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_delete_ca_pool] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.DeleteCaPoolRequest; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +public class DeleteCaPool { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, IOException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: The id of the CA pool to be deleted. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + deleteCaPool(project, location, poolId); + } + + // Delete the CA pool as mentioned by the poolId. + // Before deleting the pool, all CAs in the pool MUST BE deleted. + public static void deleteCaPool(String project, String location, String poolId) + throws InterruptedException, ExecutionException, IOException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + // Set the project, location and poolId to delete. + CaPoolName caPool = + CaPoolName.newBuilder() + .setProject(project) + .setLocation(location) + .setCaPool(poolId) + .build(); + + // Create the Delete request. + DeleteCaPoolRequest deleteCaPoolRequest = + DeleteCaPoolRequest.newBuilder().setName(caPool.toString()).build(); + + // Delete the CA Pool. + ApiFuture futureCall = + certificateAuthorityServiceClient.deleteCaPoolCallable().futureCall(deleteCaPoolRequest); + Operation response = futureCall.get(); + + if (response.hasError()) { + System.out.println("Error while deleting CA pool !" + response.getError()); + return; + } + + System.out.println("Deleted CA Pool: " + poolId); + } + } +} +// [END privateca_delete_ca_pool] diff --git a/privateca/snippets/src/main/java/privateca/DeleteCertificateAuthority.java b/privateca/snippets/src/main/java/privateca/DeleteCertificateAuthority.java new file mode 100644 index 00000000000..0f8051806af --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/DeleteCertificateAuthority.java @@ -0,0 +1,114 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_delete_ca] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CertificateAuthority.State; +import com.google.cloud.security.privateca.v1.CertificateAuthorityName; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.DeleteCertificateAuthorityRequest; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class DeleteCertificateAuthority { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: The id of the CA pool under which the CA is present. + // certificateAuthorityName: The name of the CA to be deleted. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String certificateAuthorityName = "certificate-authority-name"; + deleteCertificateAuthority(project, location, poolId, certificateAuthorityName); + } + + // Delete the Certificate Authority from the specified CA pool. + // Before deletion, the CA must be disabled and must not contain any active certificates. + public static void deleteCertificateAuthority( + String project, String location, String poolId, String certificateAuthorityName) + throws IOException, ExecutionException, InterruptedException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + // Create the Certificate Authority Name. + CertificateAuthorityName certificateAuthorityNameParent = + CertificateAuthorityName.newBuilder() + .setProject(project) + .setLocation(location) + .setCaPool(poolId) + .setCertificateAuthority(certificateAuthorityName) + .build(); + + // Check if the CA is enabled. + State caState = + certificateAuthorityServiceClient + .getCertificateAuthority(certificateAuthorityNameParent) + .getState(); + if (caState == State.ENABLED) { + System.out.println( + "Please disable the Certificate Authority before deletion ! Current state: " + caState); + return; + } + + // Create the DeleteCertificateAuthorityRequest. + // Setting the setIgnoreActiveCertificates() to true, will delete the CA + // even if it contains active certificates. Care should be taken to re-anchor + // the certificates to new CA before deleting. + DeleteCertificateAuthorityRequest deleteCertificateAuthorityRequest = + DeleteCertificateAuthorityRequest.newBuilder() + .setName(certificateAuthorityNameParent.toString()) + .setIgnoreActiveCertificates(false) + .build(); + + // Delete the Certificate Authority. + ApiFuture futureCall = + certificateAuthorityServiceClient + .deleteCertificateAuthorityCallable() + .futureCall(deleteCertificateAuthorityRequest); + Operation response = futureCall.get(); + + if (response.hasError()) { + System.out.println("Error while deleting Certificate Authority !" + response.getError()); + return; + } + + // Check if the CA has been deleted. + caState = + certificateAuthorityServiceClient + .getCertificateAuthority(certificateAuthorityNameParent) + .getState(); + if (caState == State.DELETED) { + System.out.println( + "Successfully deleted Certificate Authority : " + certificateAuthorityName); + } else { + System.out.println( + "Unable to delete Certificate Authority. Please try again ! Current state: " + caState); + } + } + } +} +// [END privateca_delete_ca] diff --git a/privateca/snippets/src/main/java/privateca/DeleteCertificateTemplate.java b/privateca/snippets/src/main/java/privateca/DeleteCertificateTemplate.java new file mode 100644 index 00000000000..c87370ec7ad --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/DeleteCertificateTemplate.java @@ -0,0 +1,79 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_delete_certificate_template] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateTemplateName; +import com.google.cloud.security.privateca.v1.DeleteCertificateTemplateRequest; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class DeleteCertificateTemplate { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + /* TODO(developer): Replace these variables before running the sample. + location: For a list of locations, see: + https://cloud.google.com/certificate-authority-service/docs/locations + certificateTemplateId: Id of the certificate template to delete. */ + String project = "your-project-id"; + String location = "ca-location"; + String certificateTemplateId = "certificate-template-id"; + + deleteCertificateTemplate(project, location, certificateTemplateId); + } + + // Deletes the certificate template present in the given project and location. + public static void deleteCertificateTemplate( + String project, String location, String certificateTemplateId) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + /* Initialize client that will be used to send requests. This client only needs to be created + once, and can be reused for multiple requests. After completing all of your requests, call + the `certificateAuthorityServiceClient.close()` method on the client to safely + clean up any remaining background resources. */ + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + // Set the parent name of the certificate template to be deleted. + DeleteCertificateTemplateRequest request = + DeleteCertificateTemplateRequest.newBuilder() + .setName( + CertificateTemplateName.of(project, location, certificateTemplateId).toString()) + .build(); + + ApiFuture futureCall = + certificateAuthorityServiceClient.deleteCertificateTemplateCallable().futureCall(request); + + Operation response = futureCall.get(60, TimeUnit.SECONDS); + + // Check for errors. + if (response.hasError()) { + System.out.println("Error deleting the certificate template ! " + response.getError()); + return; + } + + System.out.println("Successfully created certificate template ! " + response.getName()); + } + } +} +// [END privateca_delete_certificate_template] diff --git a/privateca/snippets/src/main/java/privateca/DisableCertificateAuthority.java b/privateca/snippets/src/main/java/privateca/DisableCertificateAuthority.java new file mode 100644 index 00000000000..663287d2c26 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/DisableCertificateAuthority.java @@ -0,0 +1,100 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_disable_ca] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CertificateAuthority.State; +import com.google.cloud.security.privateca.v1.CertificateAuthorityName; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.DisableCertificateAuthorityRequest; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class DisableCertificateAuthority { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: The id of the CA pool under which the CA is present. + // certificateAuthorityName: The name of the CA to be disabled. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String certificateAuthorityName = "certificate-authority-name"; + disableCertificateAuthority(project, location, poolId, certificateAuthorityName); + } + + // Disable a Certificate Authority which is present in the given CA pool. + public static void disableCertificateAuthority( + String project, String location, String poolId, String certificateAuthorityName) + throws IOException, ExecutionException, InterruptedException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + // Create the Certificate Authority Name. + CertificateAuthorityName certificateAuthorityNameParent = + CertificateAuthorityName.newBuilder() + .setProject(project) + .setLocation(location) + .setCaPool(poolId) + .setCertificateAuthority(certificateAuthorityName) + .build(); + + // Create the Disable Certificate Authority Request. + DisableCertificateAuthorityRequest disableCertificateAuthorityRequest = + DisableCertificateAuthorityRequest.newBuilder() + .setName(certificateAuthorityNameParent.toString()) + .build(); + + // Disable the Certificate Authority. + ApiFuture futureCall = + certificateAuthorityServiceClient + .disableCertificateAuthorityCallable() + .futureCall(disableCertificateAuthorityRequest); + Operation response = futureCall.get(); + + if (response.hasError()) { + System.out.println("Error while disabling Certificate Authority !" + response.getError()); + return; + } + + // Get the current CA state. + State caState = + certificateAuthorityServiceClient + .getCertificateAuthority(certificateAuthorityNameParent) + .getState(); + + // Check if the Certificate Authority is disabled. + if (caState == State.DISABLED) { + System.out.println("Disabled Certificate Authority : " + certificateAuthorityName); + } else { + System.out.println( + "Cannot disable the Certificate Authority ! Current CA State: " + caState); + } + } + } +} +// [END privateca_disable_ca] diff --git a/privateca/snippets/src/main/java/privateca/EnableCertificateAuthority.java b/privateca/snippets/src/main/java/privateca/EnableCertificateAuthority.java new file mode 100644 index 00000000000..c25156d31ba --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/EnableCertificateAuthority.java @@ -0,0 +1,96 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_enable_ca] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CertificateAuthority.State; +import com.google.cloud.security.privateca.v1.CertificateAuthorityName; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.EnableCertificateAuthorityRequest; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class EnableCertificateAuthority { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: The id of the CA pool under which the CA is present. + // certificateAuthorityName: The name of the CA to be enabled. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String certificateAuthorityName = "certificate-authority-name"; + enableCertificateAuthority(project, location, poolId, certificateAuthorityName); + } + + // Enable the Certificate Authority present in the given ca pool. + // CA cannot be enabled if it has been already deleted. + public static void enableCertificateAuthority( + String project, String location, String poolId, String certificateAuthorityName) + throws IOException, ExecutionException, InterruptedException { + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + // Create the Certificate Authority Name. + CertificateAuthorityName certificateAuthorityParent = + CertificateAuthorityName.newBuilder() + .setProject(project) + .setLocation(location) + .setCaPool(poolId) + .setCertificateAuthority(certificateAuthorityName) + .build(); + + // Create the Enable Certificate Authority Request. + EnableCertificateAuthorityRequest enableCertificateAuthorityRequest = + EnableCertificateAuthorityRequest.newBuilder() + .setName(certificateAuthorityParent.toString()) + .build(); + + // Enable the Certificate Authority. + ApiFuture futureCall = + certificateAuthorityServiceClient + .enableCertificateAuthorityCallable() + .futureCall(enableCertificateAuthorityRequest); + Operation response = futureCall.get(); + + if (response.hasError()) { + System.out.println("Error while enabling Certificate Authority !" + response.getError()); + return; + } + + // Get the current CA state. + State caState = + certificateAuthorityServiceClient + .getCertificateAuthority(certificateAuthorityParent) + .getState(); + + // Check if the CA is enabled. + if (caState == State.ENABLED) { + System.out.println("Enabled Certificate Authority : " + certificateAuthorityName); + } else { + System.out.println( + "Cannot enable the Certificate Authority ! Current CA State: " + caState); + } + } + } +} +// [END privateca_enable_ca] diff --git a/privateca/snippets/src/main/java/privateca/FilterCertificates.java b/privateca/snippets/src/main/java/privateca/FilterCertificates.java new file mode 100644 index 00000000000..de770aa8172 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/FilterCertificates.java @@ -0,0 +1,86 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_filter_certificate] + +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.Certificate; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.ListCertificatesRequest; +import java.io.IOException; + +public class FilterCertificates { + + public static void main(String[] args) throws IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Id of the CA pool which contains the certificates to be listed. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + + filterCertificates(project, location, poolId); + } + + // Filter certificates based on a condition and list them. + public static void filterCertificates(String project, String location, String poolId) + throws IOException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + CaPoolName caPool = + CaPoolName.newBuilder() + .setProject(project) + .setLocation(location) + .setCaPool(poolId) + .build(); + + // Create the certificate request and set the filter condition. + ListCertificatesRequest listCertificatesRequest = + ListCertificatesRequest.newBuilder() + .setParent(caPool.toString()) + /* Filter certificates based on the given condition. + For more info on conditions supported, + see: + https://cloud.google.com/certificate-authority-service/docs/sorting-filtering-certificates#filtering_support + Few examples for constructing conditions: + certificate_description.subject_description.not_after_time= + timestamp(com.google.protobuf) + certificate_description.subject_description.subject_alt_name.dns_names:my-dns + Here, we are filtering certificates which has organization name = csr-org-name */ + .setFilter( + "certificate_description.subject_description.subject.organization=csr-org-name") + .build(); + + // Retrieve and print the certificate names. + System.out.println("Available certificates: "); + for (Certificate certificate : + certificateAuthorityServiceClient + .listCertificates(listCertificatesRequest) + .iterateAll()) { + System.out.println(certificate.getName()); + } + } + } +} +// [END privateca_filter_certificate] diff --git a/privateca/snippets/src/main/java/privateca/ListCaPools.java b/privateca/snippets/src/main/java/privateca/ListCaPools.java new file mode 100644 index 00000000000..8573f37a701 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/ListCaPools.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_list_ca_pool] + +import com.google.cloud.security.privateca.v1.CaPool; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.LocationName; +import java.io.IOException; + +public class ListCaPools { + + public static void main(String[] args) throws IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + String project = "your-project-id"; + String location = "ca-location"; + listCaPools(project, location); + } + + // List all CA pools present in the given project and location. + public static void listCaPools(String project, String location) throws IOException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + // Set the Location Name which contains project and location of the pool. + LocationName locationName = + LocationName.newBuilder().setProject(project).setLocation(location).build(); + + String caPoolName = ""; + System.out.println("Available CA pools: "); + + // List the CA pools. + for (CaPool caPool : + certificateAuthorityServiceClient.listCaPools(locationName).iterateAll()) { + caPoolName = caPool.getName(); + // caPoolName represents the full resource name of the + // format 'projects/{project-id}/locations/{location}/ca-pools/{ca-pool-id}'. + // Hence stripping it down to just CA pool id. + System.out.println( + caPoolName.substring(caPoolName.lastIndexOf("/") + 1) + " " + caPool.isInitialized()); + } + } + } +} +// [END privateca_list_ca_pool] diff --git a/privateca/snippets/src/main/java/privateca/ListCertificateAuthorities.java b/privateca/snippets/src/main/java/privateca/ListCertificateAuthorities.java new file mode 100644 index 00000000000..a33f5345764 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/ListCertificateAuthorities.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_list_ca] + +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.CertificateAuthority; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import java.io.IOException; + +public class ListCertificateAuthorities { + + public static void main(String[] args) throws IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: The id of the CA pool under which the CAs to be listed are present. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + listCertificateAuthority(project, location, poolId); + } + + // List all Certificate authorities present in the given CA Pool. + public static void listCertificateAuthority(String project, String location, String poolId) + throws IOException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + // Create CA pool name comprising of project, location and the pool name. + CaPoolName parent = + CaPoolName.newBuilder() + .setProject(project) + .setLocation(location) + .setCaPool(poolId) + .build(); + + // List the CA name and its corresponding state. + for (CertificateAuthority certificateAuthority : + certificateAuthorityServiceClient.listCertificateAuthorities(parent).iterateAll()) { + System.out.println( + certificateAuthority.getName() + " is " + certificateAuthority.getState()); + } + } + } +} +// [END privateca_list_ca] diff --git a/privateca/snippets/src/main/java/privateca/ListCertificateTemplates.java b/privateca/snippets/src/main/java/privateca/ListCertificateTemplates.java new file mode 100644 index 00000000000..cc726fda701 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/ListCertificateTemplates.java @@ -0,0 +1,74 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_list_certificate_template] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateTemplate; +import com.google.cloud.security.privateca.v1.ListCertificateTemplatesRequest; +import com.google.cloud.security.privateca.v1.ListCertificateTemplatesResponse; +import com.google.cloud.security.privateca.v1.LocationName; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class ListCertificateTemplates { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + /* TODO(developer): Replace these variables before running the sample. + location: For a list of locations, see: + https://cloud.google.com/certificate-authority-service/docs/locations */ + String project = "your-project-id"; + String location = "ca-location"; + + listCertificateTemplates(project, location); + } + + // Lists the certificate templates present in the given project and location. + public static void listCertificateTemplates(String project, String location) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + /* Initialize client that will be used to send requests. This client only needs to be created + once, and can be reused for multiple requests. After completing all of your requests, call + the `certificateAuthorityServiceClient.close()` method on the client to safely + clean up any remaining background resources. */ + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + // Set the parent name to list the certificate templates. + ListCertificateTemplatesRequest request = + ListCertificateTemplatesRequest.newBuilder() + .setParent(LocationName.of(project, location).toString()) + .build(); + + ApiFuture futureCall = + certificateAuthorityServiceClient.listCertificateTemplatesCallable().futureCall(request); + + // Get the response. + ListCertificateTemplatesResponse response = futureCall.get(60, TimeUnit.SECONDS); + + // List all templates. + for (CertificateTemplate template : response.getCertificateTemplatesList()) { + System.out.println(template.getName()); + } + } + } +} +// [END privateca_list_certificate_template] diff --git a/privateca/snippets/src/main/java/privateca/ListCertificates.java b/privateca/snippets/src/main/java/privateca/ListCertificates.java new file mode 100644 index 00000000000..ef1646b8d75 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/ListCertificates.java @@ -0,0 +1,65 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_list_certificate] + +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.Certificate; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import java.io.IOException; + +public class ListCertificates { + + public static void main(String[] args) throws IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Id of the CA pool which contains the certificates to be listed. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + listCertificates(project, location, poolId); + } + + // List Certificates present in the given CA pool. + public static void listCertificates(String project, String location, String poolId) + throws IOException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + CaPoolName caPool = + CaPoolName.newBuilder() + .setProject(project) + .setLocation(location) + .setCaPool(poolId) + .build(); + + // Retrieve and print the certificate names. + System.out.println("Available certificates: "); + for (Certificate certificate : + certificateAuthorityServiceClient.listCertificates(caPool).iterateAll()) { + System.out.println(certificate.getName()); + } + } + } +} +// [END privateca_list_certificate] diff --git a/privateca/snippets/src/main/java/privateca/MonitorCertificateAuthority.java b/privateca/snippets/src/main/java/privateca/MonitorCertificateAuthority.java new file mode 100644 index 00000000000..0b21ec4f3c3 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/MonitorCertificateAuthority.java @@ -0,0 +1,92 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_monitor_ca_expiry] + +import com.google.cloud.monitoring.v3.AlertPolicyServiceClient; +import com.google.cloud.monitoring.v3.NotificationChannelServiceClient; +import com.google.monitoring.v3.AlertPolicy; +import com.google.monitoring.v3.AlertPolicy.Condition; +import com.google.monitoring.v3.AlertPolicy.Condition.MonitoringQueryLanguageCondition; +import com.google.monitoring.v3.AlertPolicy.ConditionCombinerType; +import com.google.monitoring.v3.NotificationChannel; +import com.google.monitoring.v3.ProjectName; +import java.io.IOException; + +public class MonitorCertificateAuthority { + + public static void main(String[] args) throws IOException { + // TODO(developer): Replace these variables before running the sample. + String project = "your-project-id"; + createCaMonitoringPolicy(project); + } + + // Creates a monitoring policy that notifies you 30 days before a managed CA expires. + public static void createCaMonitoringPolicy(String project) throws IOException { + /* Initialize client that will be used to send requests. This client only needs to be created + once, and can be reused for multiple requests. After completing all of your requests, call + the `client.close()` method on the client to safely + clean up any remaining background resources. */ + try (AlertPolicyServiceClient client = AlertPolicyServiceClient.create(); + NotificationChannelServiceClient notificationClient = + NotificationChannelServiceClient.create()) { + + String policyName = "policy-name"; + + /* Query which indicates the resource to monitor and the constraints. + Here, the alert policy notifies you 30 days before a managed CA expires. + For more info on creating queries, see: https://cloud.google.com/monitoring/mql/alerts */ + String query = + "fetch privateca.googleapis.com/CertificateAuthority" + + "| metric 'privateca.googleapis.com/ca/cert_chain_expiration'" + + "| group_by 5m," + + "[value_cert_chain_expiration_mean: mean(value.cert_chain_expiration)]" + + "| every 5m" + + "| condition val() < 2.592e+06 's'"; + + // Create a notification channel. + NotificationChannel notificationChannel = + NotificationChannel.newBuilder() + .setType("email") + .putLabels("email_address", "java-docs-samples-testing@google.com") + .build(); + NotificationChannel channel = + notificationClient.createNotificationChannel( + ProjectName.of(project), notificationChannel); + + // Set the query and notification channel. + AlertPolicy alertPolicy = + AlertPolicy.newBuilder() + .setDisplayName(policyName) + .addConditions( + Condition.newBuilder() + .setDisplayName("ca-cert-chain-expiration") + .setConditionMonitoringQueryLanguage( + MonitoringQueryLanguageCondition.newBuilder().setQuery(query).build()) + .build()) + .setCombiner(ConditionCombinerType.AND) + .addNotificationChannels(channel.getName()) + .build(); + + AlertPolicy policy = client.createAlertPolicy(ProjectName.of(project), alertPolicy); + + System.out.println("Monitoring policy successfully created !" + policy.getName()); + } + } +} +// [END privateca_monitor_ca_expiry] diff --git a/privateca/snippets/src/main/java/privateca/RevokeCertificate.java b/privateca/snippets/src/main/java/privateca/RevokeCertificate.java new file mode 100644 index 00000000000..1c6a10dc273 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/RevokeCertificate.java @@ -0,0 +1,85 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_revoke_certificate] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.Certificate; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateName; +import com.google.cloud.security.privateca.v1.RevocationReason; +import com.google.cloud.security.privateca.v1.RevokeCertificateRequest; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class RevokeCertificate { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Id for the CA pool which contains the certificate. + // certificateName: Name of the certificate to be revoked. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String certificateName = "certificate-name"; + revokeCertificate(project, location, poolId, certificateName); + } + + // Revoke an issued certificate. Once revoked, the certificate will become invalid and will expire + // post its lifetime. + public static void revokeCertificate( + String project, String location, String poolId, String certificateName) + throws IOException, ExecutionException, InterruptedException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + // Create Certificate Name. + CertificateName certificateNameParent = + CertificateName.newBuilder() + .setProject(project) + .setLocation(location) + .setCaPool(poolId) + .setCertificate(certificateName) + .build(); + + // Create Revoke Certificate Request and specify the appropriate revocation reason. + RevokeCertificateRequest revokeCertificateRequest = + RevokeCertificateRequest.newBuilder() + .setName(certificateNameParent.toString()) + .setReason(RevocationReason.PRIVILEGE_WITHDRAWN) + .build(); + + // Revoke certificate. + ApiFuture response = + certificateAuthorityServiceClient + .revokeCertificateCallable() + .futureCall(revokeCertificateRequest); + Certificate certificateResponse = response.get(); + + System.out.println("Certificate Revoked: " + certificateResponse.getName()); + } + } +} +// [END privateca_revoke_certificate] diff --git a/privateca/snippets/src/main/java/privateca/UndeleteCertificateAuthority.java b/privateca/snippets/src/main/java/privateca/UndeleteCertificateAuthority.java new file mode 100644 index 00000000000..ba83f568ee9 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/UndeleteCertificateAuthority.java @@ -0,0 +1,108 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_undelete_ca] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CertificateAuthority.State; +import com.google.cloud.security.privateca.v1.CertificateAuthorityName; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.UndeleteCertificateAuthorityRequest; +import com.google.longrunning.Operation; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class UndeleteCertificateAuthority { + + public static void main(String[] args) + throws InterruptedException, ExecutionException, TimeoutException, IOException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: The id of the CA pool under which the deleted CA is present. + // certificateAuthorityName: The name of the CA to be restored (undeleted). + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String certificateAuthorityName = "certificate-authority-name"; + + undeleteCertificateAuthority(project, location, poolId, certificateAuthorityName); + } + + // Restore a deleted CA, if still within the grace period of 30 days. + public static void undeleteCertificateAuthority( + String project, String location, String poolId, String certificateAuthorityName) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the `certificateAuthorityServiceClient.close()` method on the client to safely + // clean up any remaining background resources. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + String certificateAuthorityParent = + CertificateAuthorityName.of(project, location, poolId, certificateAuthorityName) + .toString(); + + // Confirm if the CA is in DELETED stage. + if (getCurrentState(certificateAuthorityServiceClient, certificateAuthorityParent) + != State.DELETED) { + System.out.println("CA is not deleted !"); + return; + } + + // Create the Request. + UndeleteCertificateAuthorityRequest undeleteCertificateAuthorityRequest = + UndeleteCertificateAuthorityRequest.newBuilder() + .setName(certificateAuthorityParent) + .build(); + + // Undelete the CA. + ApiFuture futureCall = + certificateAuthorityServiceClient + .undeleteCertificateAuthorityCallable() + .futureCall(undeleteCertificateAuthorityRequest); + + Operation response = futureCall.get(5, TimeUnit.SECONDS); + + // CA state changes from DELETED to DISABLED if successfully restored. + // Confirm if the CA is DISABLED. + if (response.hasError() + || getCurrentState(certificateAuthorityServiceClient, certificateAuthorityParent) + != State.DISABLED) { + System.out.println( + "Unable to restore the Certificate Authority! Please try again !" + + response.getError()); + return; + } + + // The CA will be in the DISABLED state. Enable before use. + System.out.println( + "Successfully restored the Certificate Authority ! " + certificateAuthorityName); + } + } + + // Get the current state of CA. + private static State getCurrentState( + CertificateAuthorityServiceClient client, String certificateAuthorityParent) { + return client.getCertificateAuthority(certificateAuthorityParent).getState(); + } +} +// [END privateca_undelete_ca] diff --git a/privateca/snippets/src/main/java/privateca/UpdateCaPoolIssuancePolicy.java b/privateca/snippets/src/main/java/privateca/UpdateCaPoolIssuancePolicy.java new file mode 100644 index 00000000000..86f20669f38 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/UpdateCaPoolIssuancePolicy.java @@ -0,0 +1,136 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_set_issuance_policy] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CaPool; +import com.google.cloud.security.privateca.v1.CaPool.IssuancePolicy; +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateIdentityConstraints; +import com.google.cloud.security.privateca.v1.UpdateCaPoolRequest; +import com.google.longrunning.Operation; +import com.google.protobuf.FieldMask; +import com.google.type.Expr; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class UpdateCaPoolIssuancePolicy { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: The CA pool for which the issuance policy is to be updated. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + + updateCaPoolIssuancePolicy(project, location, poolId); + } + + /* Update the Issuance policy for a CA Pool. All certificates issued from this CA Pool should + meet the issuance policy. */ + public static void updateCaPoolIssuancePolicy(String project, String location, String poolId) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + /* Initialize client that will be used to send requests. This client only needs to be created + once, and can be reused for multiple requests. After completing all of your requests, call + the `certificateAuthorityServiceClient.close()` method on the client to safely + clean up any remaining background resources. */ + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + /* Set the updated issuance policy for the CA Pool. + This particular issuance policy allows only SANs that + have DNS Names as "us.google.org" or ending in ".google.com". */ + String expr = + "subject_alt_names.all(san, san.type == DNS && (san.value == \"dns.example.com\"" + + " || san.value.endsWith(\".example.com\")) )"; + + CaPool.IssuancePolicy issuancePolicy = + IssuancePolicy.newBuilder() + .setIdentityConstraints( + CertificateIdentityConstraints.newBuilder() + .setAllowSubjectPassthrough(true) + .setAllowSubjectAltNamesPassthrough(true) + .setCelExpression(Expr.newBuilder().setExpression(expr).build()) + .build()) + .build(); + + CaPool caPool = + CaPool.newBuilder() + .setName(CaPoolName.of(project, location, poolId).toString()) + .setIssuancePolicy(issuancePolicy) + .build(); + + /* 1. Set the CA pool with updated values. + 2. Set the update mask to specify which properties of the CA Pool should be updated. + Only the properties specified in the mask will be updated. Make sure that the mask fields + match the updated issuance policy. + For more info on constructing path for update mask, see: + https://cloud.google.com/certificate-authority-service/docs/reference/rest/v1/projects.locations.caPools#issuancepolicy */ + UpdateCaPoolRequest updateCaPoolRequest = + UpdateCaPoolRequest.newBuilder() + .setCaPool(caPool) + .setUpdateMask( + FieldMask.newBuilder( + FieldMask.newBuilder() + .addPaths( + "issuance_policy.identity_constraints.allow_subject_passthrough") + .addPaths( + "issuance_policy.identity_constraints." + + "allow_subject_alt_names_passthrough") + .addPaths("issuance_policy.identity_constraints.cel_expression") + .build())) + .build(); + + // Update CA Pool request. + ApiFuture futureCall = + certificateAuthorityServiceClient.updateCaPoolCallable().futureCall(updateCaPoolRequest); + + Operation operation = futureCall.get(60, TimeUnit.SECONDS); + + // Check for errors. + if (operation.hasError()) { + System.out.println("Error in updating CA Pool Issuance policy ! " + operation.getError()); + return; + } + + // Get the CA Pool's issuance policy and verify if the fields have been successfully updated. + IssuancePolicy response = + certificateAuthorityServiceClient + .getCaPool(CaPoolName.of(project, location, poolId).toString()) + .getIssuancePolicy(); + + // Similarly, you can check for other modified fields as well. + if (response.getIdentityConstraints().getAllowSubjectPassthrough() + && response.getIdentityConstraints().getAllowSubjectAltNamesPassthrough()) { + System.out.println("CA Pool Issuance policy has been updated successfully ! "); + return; + } + + System.out.println( + "Error in updating CA Pool Issuance policy ! Please try again ! " + response); + } + } +} +// [END privateca_set_issuance_policy] diff --git a/privateca/snippets/src/main/java/privateca/UpdateCertificateAuthority.java b/privateca/snippets/src/main/java/privateca/UpdateCertificateAuthority.java new file mode 100644 index 00000000000..4c0868f793f --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/UpdateCertificateAuthority.java @@ -0,0 +1,100 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_update_ca_label] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CertificateAuthority; +import com.google.cloud.security.privateca.v1.CertificateAuthorityName; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.UpdateCertificateAuthorityRequest; +import com.google.longrunning.Operation; +import com.google.protobuf.FieldMask; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class UpdateCertificateAuthority { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // poolId: Set it to the CA Pool under which the CA should be created. + // certificateAuthorityName: Unique name for the CA. + String project = "your-project-id"; + String location = "ca-location"; + String poolId = "ca-pool-id"; + String certificateAuthorityName = "certificate-authority-name"; + + updateCaLabel(project, location, poolId, certificateAuthorityName); + } + + // Updates the labels in a certificate authority. + public static void updateCaLabel( + String project, String location, String poolId, String certificateAuthorityName) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + /* Initialize client that will be used to send requests. This client only needs to be created + once, and can be reused for multiple requests. After completing all of your requests, call + the `certificateAuthorityServiceClient.close()` method on the client to safely + clean up any remaining background resources. */ + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + // Set the parent path and the new labels. + String certificateAuthorityParent = + CertificateAuthorityName.of(project, location, poolId, certificateAuthorityName) + .toString(); + CertificateAuthority certificateAuthority = + CertificateAuthority.newBuilder() + .setName(certificateAuthorityParent) + .putLabels("env", "test") + .build(); + + // Create a request to update the CA. + UpdateCertificateAuthorityRequest request = + UpdateCertificateAuthorityRequest.newBuilder() + .setCertificateAuthority(certificateAuthority) + .setUpdateMask(FieldMask.newBuilder().addPaths("labels").build()) + .build(); + + // Update the CA and wait for the operation to complete. + ApiFuture futureCall = + certificateAuthorityServiceClient + .updateCertificateAuthorityCallable() + .futureCall(request); + Operation operation = futureCall.get(60, TimeUnit.SECONDS); + + // Check for errors. + if (operation.hasError()) { + System.out.println("Error in updating labels ! " + operation.getError()); + } + + // Get the updated CA and check if it contains the new label. + CertificateAuthority response = + certificateAuthorityServiceClient.getCertificateAuthority(certificateAuthorityParent); + if (response.getLabelsMap().containsKey("env") + && response.getLabelsMap().get("env").equalsIgnoreCase("test")) { + System.out.println("Successfully updated the labels ! "); + } + } + } +} +// [END privateca_update_ca_label] diff --git a/privateca/snippets/src/main/java/privateca/UpdateCertificateTemplate.java b/privateca/snippets/src/main/java/privateca/UpdateCertificateTemplate.java new file mode 100644 index 00000000000..5cc93568671 --- /dev/null +++ b/privateca/snippets/src/main/java/privateca/UpdateCertificateTemplate.java @@ -0,0 +1,117 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +// [START privateca_update_certificate_template] + +import com.google.api.core.ApiFuture; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateIdentityConstraints; +import com.google.cloud.security.privateca.v1.CertificateTemplate; +import com.google.cloud.security.privateca.v1.CertificateTemplateName; +import com.google.cloud.security.privateca.v1.UpdateCertificateTemplateRequest; +import com.google.longrunning.Operation; +import com.google.protobuf.FieldMask; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class UpdateCertificateTemplate { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // location: For a list of locations, see: + // https://cloud.google.com/certificate-authority-service/docs/locations + // certificateTemplateId: Id of the certificate template to update. + String project = "your-project-id"; + String location = "ca-location"; + String certificateTemplateId = "certificate-template-id"; + + updateCertificateTemplate(project, location, certificateTemplateId); + } + + // Updates an existing certificate template. + public static void updateCertificateTemplate( + String project, String location, String certificateTemplateId) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + /* Initialize client that will be used to send requests. This client only needs to be created + once, and can be reused for multiple requests. After completing all of your requests, call + the `certificateAuthorityServiceClient.close()` method on the client to safely + clean up any remaining background resources. */ + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + + String certificateTemplateName = + CertificateTemplateName.of(project, location, certificateTemplateId).toString(); + + // Set the parent name and the properties to be updated. + CertificateTemplate certificateTemplate = + CertificateTemplate.newBuilder() + .setName(certificateTemplateName) + .setIdentityConstraints( + CertificateIdentityConstraints.newBuilder() + .setAllowSubjectPassthrough(false) + .setAllowSubjectAltNamesPassthrough(true) + .build()) + .build(); + + // Set the mask corresponding to the properties updated above. + FieldMask fieldMask = + FieldMask.newBuilder() + .addPaths("identity_constraints.allow_subject_alt_names_passthrough") + .addPaths("identity_constraints.allow_subject_passthrough") + .build(); + + /* Set the new template. + Set the mask to specify which properties of the template should be updated. */ + UpdateCertificateTemplateRequest request = + UpdateCertificateTemplateRequest.newBuilder() + .setCertificateTemplate(certificateTemplate) + .setUpdateMask(fieldMask) + .build(); + + // Create the update certificate template request. + ApiFuture futureCall = + certificateAuthorityServiceClient.updateCertificateTemplateCallable().futureCall(request); + + Operation response = futureCall.get(60, TimeUnit.SECONDS); + + // Check for errors. + if (response.hasError()) { + System.out.println("Error in updating certificate template ! " + response.getError()); + return; + } + + // Get the updated certificate template and check if the properties have been updated. + CertificateIdentityConstraints updatedCertificateIdentityConstraints = + certificateAuthorityServiceClient + .getCertificateTemplate(certificateTemplateName) + .getIdentityConstraints(); + + if (!updatedCertificateIdentityConstraints.getAllowSubjectPassthrough() + && updatedCertificateIdentityConstraints.getAllowSubjectAltNamesPassthrough()) { + System.out.println("Successfully updated the certificate template ! " + response.getName()); + return; + } + + System.out.println("Error in updating certificate template ! "); + } + } +} +// [END privateca_update_certificate_template] diff --git a/privateca/snippets/src/test/java/privateca/SnippetsIT.java b/privateca/snippets/src/test/java/privateca/SnippetsIT.java new file mode 100644 index 00000000000..446974f6350 --- /dev/null +++ b/privateca/snippets/src/test/java/privateca/SnippetsIT.java @@ -0,0 +1,476 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package privateca; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import com.google.cloud.security.privateca.v1.CaPool.IssuancePolicy; +import com.google.cloud.security.privateca.v1.CaPoolName; +import com.google.cloud.security.privateca.v1.Certificate; +import com.google.cloud.security.privateca.v1.CertificateAuthority; +import com.google.cloud.security.privateca.v1.CertificateAuthorityName; +import com.google.cloud.security.privateca.v1.CertificateAuthorityServiceClient; +import com.google.cloud.security.privateca.v1.CertificateName; +import com.google.cloud.security.privateca.v1.CertificateTemplateName; +import com.google.cloud.security.privateca.v1.FetchCertificateAuthorityCsrResponse; +import com.google.protobuf.ByteString; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.util.io.pem.PemObject; +import org.bouncycastle.util.io.pem.PemWriter; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class SnippetsIT { + + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static String LOCATION; + private static String CA_poolId; + private static String CA_poolId_DELETE; + private static String CA_NAME; + private static String CA_NAME_DELETE; + private static String SUBORDINATE_CA_NAME; + private static String CERTIFICATE_TEMPLATE_NAME; + private static String CERTIFICATE_NAME; + private static String CSR_CERTIFICATE_NAME; + private static int KEY_SIZE; + + private ByteArrayOutputStream stdOut; + + // Check if the required environment variables are set. + public static void reqEnvVar(String envVarName) { + assertWithMessage(String.format("Missing environment variable '%s' ", envVarName)) + .that(System.getenv(envVarName)) + .isNotEmpty(); + } + + @BeforeClass + public static void setUp() + throws IOException, ExecutionException, NoSuchProviderException, NoSuchAlgorithmException, + InterruptedException, TimeoutException { + reqEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + reqEnvVar("GOOGLE_CLOUD_PROJECT"); + + LOCATION = "asia-south1"; + CA_poolId = "ca-pool-" + UUID.randomUUID(); + CA_poolId_DELETE = "ca-pool-" + UUID.randomUUID(); + CA_NAME = "ca-name-" + UUID.randomUUID(); + CA_NAME_DELETE = "ca-name-" + UUID.randomUUID(); + SUBORDINATE_CA_NAME = "sub-ca-name-" + UUID.randomUUID(); + CERTIFICATE_TEMPLATE_NAME = "certificate-template-name-" + UUID.randomUUID(); + CERTIFICATE_NAME = "certificate-name-" + UUID.randomUUID(); + CSR_CERTIFICATE_NAME = "csr-certificate-name-" + UUID.randomUUID(); + KEY_SIZE = 2048; // Default key size + + // <--- START CA POOL ---> + // Create CA Pool. + privateca.CreateCaPool.createCaPool(PROJECT_ID, LOCATION, CA_poolId); + privateca.CreateCaPool.createCaPool(PROJECT_ID, LOCATION, CA_poolId_DELETE); + sleep(5); + // Set the issuance policy for the created CA Pool. + UpdateCaPoolIssuancePolicy.updateCaPoolIssuancePolicy( + PROJECT_ID, LOCATION, CA_poolId); + // <--- END CA POOL ---> + + // <--- START ROOT CA ---> + // Create and Enable Certificate Authority. + privateca.CreateCertificateAuthority.createCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME); + sleep(10); + privateca.EnableCertificateAuthority.enableCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME); + + // Create and Delete Certificate Authority. + privateca.CreateCertificateAuthority.createCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME_DELETE); + sleep(10); + privateca.DeleteCertificateAuthority.deleteCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME_DELETE); + // <--- END ROOT CA ---> + + // <--- START SUBORDINATE CA ---> + // Follow the below steps to create and enable a Subordinate Certificate Authority. + // 1. Create a Subordinate Certificate Authority. + privateca.CreateSubordinateCa.createSubordinateCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, SUBORDINATE_CA_NAME); + sleep(10); + // 2. Fetch CSR. + String pemCsr = fetchPemCSR(CA_poolId, SUBORDINATE_CA_NAME); + // 3. Sign the CSR, and create a certificate. + CreateCertificateCsr.createCertificateWithCsr( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME, CSR_CERTIFICATE_NAME, pemCsr); + // <--- END SUBORDINATE CA ---> + + // <--- START CERTIFICATE ---> + // Create Certificate Template. + privateca.CreateCertificateTemplate.createCertificateTemplate( + PROJECT_ID, LOCATION, CERTIFICATE_TEMPLATE_NAME); + + // Create an asymmetric key pair using Bouncy Castle crypto framework. + KeyPair asymmetricKeyPair = createAsymmetricKeyPair(); + + // Cast the keys to their respective components. + RSAPublicKey publicKey = (RSAPublicKey) asymmetricKeyPair.getPublic(); + RSAPrivateKey privateKey = (RSAPrivateKey) asymmetricKeyPair.getPrivate(); + + // Construct the PemObject for public and private keys. + PemObject publicKeyPemObject = new PemObject("PUBLIC KEY", publicKey.getEncoded()); + PemObject privateKeyPemObject = new PemObject("PRIVATE KEY", privateKey.getEncoded()); + + // Only the public key will be used to create the certificate. + ByteString publicKeyByteString = convertToPemEncodedByteString(publicKeyPemObject); + + // TODO (Developers): Save the private key by writing it to a file and + // TODO (cont): use it to verify the issued certificate. + ByteString privateKeyByteString = convertToPemEncodedByteString(privateKeyPemObject); + + // Create certificate with the above generated public key. + privateca.CreateCertificate.createCertificate( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME, CERTIFICATE_NAME, publicKeyByteString); + sleep(5); + // <--- END CERTIFICATE ---> + } + + @AfterClass + public static void cleanUp() + throws InterruptedException, ExecutionException, IOException, TimeoutException { + + ByteArrayOutputStream stdOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOut)); + + // Revoke Certificate. + privateca.RevokeCertificate.revokeCertificate( + PROJECT_ID, LOCATION, CA_poolId, CSR_CERTIFICATE_NAME); + + // Delete Certificate Template. + privateca.DeleteCertificateTemplate.deleteCertificateTemplate( + PROJECT_ID, LOCATION, CERTIFICATE_TEMPLATE_NAME); + + // Delete root CA. + privateca.DeleteCertificateAuthority.deleteCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME); + sleep(5); + // Deleting the undeleted CA. + privateca.DeleteCertificateAuthority.deleteCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME_DELETE); + + // Delete Subordinate CA. + privateca.DeleteCertificateAuthority.deleteCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, SUBORDINATE_CA_NAME); + sleep(5); + // Delete CA Pool. + privateca.DeleteCaPool.deleteCaPool(PROJECT_ID, LOCATION, CA_poolId); + + stdOut = null; + System.setOut(null); + } + + // Wait for the specified amount of time. + public static void sleep(int seconds) throws InterruptedException { + TimeUnit.SECONDS.sleep(seconds); + } + + // Fetch CSR of the given CA. + public static String fetchPemCSR(String poolId, String caName) throws IOException { + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + String caParent = + CertificateAuthorityName.of(PROJECT_ID, LOCATION, poolId, caName).toString(); + + FetchCertificateAuthorityCsrResponse response = + certificateAuthorityServiceClient.fetchCertificateAuthorityCsr(caParent); + + return response.getPemCsr(); + } + } + + // Create an asymmetric key pair to be used in certificate signing. + public static KeyPair createAsymmetricKeyPair() + throws NoSuchAlgorithmException, NoSuchProviderException { + Security.addProvider(new BouncyCastleProvider()); + + // Generate the key pair with RSA algorithm using Bouncy Castle (BC). + KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC"); + generator.initialize(KEY_SIZE); + KeyPair keyPair = generator.generateKeyPair(); + + return keyPair; + } + + // Convert the encoded PemObject to ByteString. + public static ByteString convertToPemEncodedByteString(PemObject pemEncodedKey) + throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + PemWriter pemWriter = new PemWriter(new OutputStreamWriter(byteArrayOutputStream)); + pemWriter.writeObject(pemEncodedKey); + pemWriter.close(); + ByteString keyByteString = ByteString.copyFrom(byteArrayOutputStream.toByteArray()); + + return keyByteString; + } + + @Before + public void beforeEach() { + stdOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOut)); + } + + @After + public void afterEach() { + stdOut = null; + System.setOut(null); + } + + @Test + public void testCreateCAPool() throws IOException { + // Check if the CA pool created during setup is successful. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + String caPoolName = + certificateAuthorityServiceClient + .getCaPool(CaPoolName.of(PROJECT_ID, LOCATION, CA_poolId).toString()) + .getName(); + assertThat(caPoolName) + .contains( + String.format( + "projects/%s/locations/%s/caPools/%s", PROJECT_ID, LOCATION, CA_poolId)); + } + } + + @Test + public void testUpdateCAPoolIssuancePolicy() throws IOException { + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + IssuancePolicy issuancePolicy = + certificateAuthorityServiceClient + .getCaPool(CaPoolName.of(PROJECT_ID, LOCATION, CA_poolId).toString()) + .getIssuancePolicy(); + + String actualExpression = + issuancePolicy.getIdentityConstraints().getCelExpression().getExpression(); + String expectedExpression = + "subject_alt_names.all(san, san.type == DNS && (san.value == \"dns.example.com\" || " + + "san.value.endsWith(\".example.com\")) )"; + assertThat(actualExpression).contains(expectedExpression); + } + } + + @Test + public void testListCAPools() throws IOException { + privateca.ListCaPools.listCaPools(PROJECT_ID, LOCATION); + assertThat(stdOut.toString()).contains(CA_poolId); + } + + @Test + public void testDeleteCAPool() + throws InterruptedException, ExecutionException, IOException, TimeoutException { + privateca.DeleteCaPool.deleteCaPool(PROJECT_ID, LOCATION, CA_poolId_DELETE); + assertThat(stdOut.toString()).contains("Deleted CA Pool: " + CA_poolId_DELETE); + } + + @Test + public void testCreateCertificateAuthority() throws IOException { + // Check if the CA created during setup is successful. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + CertificateAuthority response = + certificateAuthorityServiceClient.getCertificateAuthority( + CertificateAuthorityName.of(PROJECT_ID, LOCATION, CA_poolId, CA_NAME).toString()); + assertThat(response.getName()).contains(CA_NAME); + } + } + + @Test + public void testListCertificateAuthorities() throws IOException { + privateca.ListCertificateAuthorities.listCertificateAuthority(PROJECT_ID, LOCATION, CA_poolId); + assertThat(stdOut.toString()).contains(CA_NAME); + } + + @Test + public void testUpdateCertificateAuthority() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + privateca.UpdateCertificateAuthority.updateCaLabel(PROJECT_ID, LOCATION, CA_poolId, CA_NAME); + assertThat(stdOut.toString()).contains("Successfully updated the labels ! "); + } + + @Test + public void testMonitorCertificateAuthority() throws IOException, InterruptedException { + privateca.MonitorCertificateAuthority.createCaMonitoringPolicy(PROJECT_ID); + assertThat(stdOut.toString()).contains("Monitoring policy successfully created !"); + } + + @Test + public void testEnableDisableCertificateAuthority() + throws InterruptedException, ExecutionException, IOException { + privateca.EnableCertificateAuthority.enableCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME); + assertThat(stdOut.toString()).contains("Enabled Certificate Authority : " + CA_NAME); + privateca.DisableCertificateAuthority.disableCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME); + assertThat(stdOut.toString()).contains("Disabled Certificate Authority : " + CA_NAME); + } + + @Test + public void testDeleteUndeleteCertificateAuthority() + throws InterruptedException, ExecutionException, IOException, TimeoutException { + // CA deleted as part of setup(). Undelete the CA. + // The undelete operation will be executed only if the CA was successfully deleted. + privateca.UndeleteCertificateAuthority.undeleteCertificateAuthority( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME_DELETE); + assertThat(stdOut.toString()) + .contains("Successfully restored the Certificate Authority ! " + CA_NAME_DELETE); + } + + @Test + public void testCreateCertificateTemplate() throws IOException { + // Check that the Certificate template has been created as part of the setup. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + String certificateTemplate = + certificateAuthorityServiceClient + .getCertificateTemplate( + CertificateTemplateName.of(PROJECT_ID, LOCATION, CERTIFICATE_TEMPLATE_NAME) + .toString()) + .getName(); + + assertThat(certificateTemplate) + .contains(String.format("projects/%s/locations/%s/", PROJECT_ID, LOCATION)); + } + } + + @Test + public void testListCertificateTemplate() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + privateca.ListCertificateTemplates.listCertificateTemplates(PROJECT_ID, LOCATION); + assertThat(stdOut.toString()).contains(CERTIFICATE_TEMPLATE_NAME); + } + + @Test + public void updateCertificateTemplate() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + privateca.UpdateCertificateTemplate.updateCertificateTemplate( + PROJECT_ID, LOCATION, CERTIFICATE_TEMPLATE_NAME); + assertThat(stdOut.toString()).contains("Successfully updated the certificate template ! "); + } + + @Test + public void testCreateCertificate() throws IOException { + // Check if the certificate created during setup is successful. + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + CertificateName certificateName = + CertificateName.of(PROJECT_ID, LOCATION, CA_poolId, CERTIFICATE_NAME); + Certificate certificate = certificateAuthorityServiceClient.getCertificate(certificateName); + assertThat(certificate.getName()).contains(CERTIFICATE_NAME); + } + } + + @Test + public void testListCertificates() throws IOException { + privateca.ListCertificates.listCertificates(PROJECT_ID, LOCATION, CA_poolId); + assertThat(stdOut.toString()).contains(CERTIFICATE_NAME); + } + + @Test + public void testFilterCertificates() throws IOException { + // Filter only certificates created using CSR. + privateca.FilterCertificates.filterCertificates(PROJECT_ID, LOCATION, CA_poolId); + assertThat(stdOut.toString()).contains(CSR_CERTIFICATE_NAME); + assertThat(stdOut.toString()).doesNotContain(CERTIFICATE_NAME); + } + + @Test + public void testRevokeCertificate() throws InterruptedException, ExecutionException, IOException { + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + // Revoke the certificate. + privateca.RevokeCertificate.revokeCertificate( + PROJECT_ID, LOCATION, CA_poolId, CERTIFICATE_NAME); + + // Check if the certificate has revocation details. If it does, then the certificate is + // considered as revoked. + CertificateName certificateName = + CertificateName.of(PROJECT_ID, LOCATION, CA_poolId, CERTIFICATE_NAME); + Assert.assertTrue( + certificateAuthorityServiceClient.getCertificate(certificateName).hasRevocationDetails()); + } + } + + @Test + public void testCreateSubordinateCertificateAuthority() throws IOException { + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + CertificateAuthority response = + certificateAuthorityServiceClient.getCertificateAuthority( + CertificateAuthorityName.of(PROJECT_ID, LOCATION, CA_poolId, SUBORDINATE_CA_NAME) + .toString()); + Assert.assertTrue(response.hasCreateTime()); + } + } + + @Test + public void testCreateCertificateWithCSR() throws IOException { + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + Certificate response = + certificateAuthorityServiceClient.getCertificate( + CertificateName.of(PROJECT_ID, LOCATION, CA_poolId, CSR_CERTIFICATE_NAME) + .toString()); + Assert.assertTrue(response.hasCreateTime()); + } + } + + @Test + public void testActivateSubordinateCertificateAuthority() + throws IOException, ExecutionException, InterruptedException { + try (CertificateAuthorityServiceClient certificateAuthorityServiceClient = + CertificateAuthorityServiceClient.create()) { + Certificate response = + certificateAuthorityServiceClient.getCertificate( + CertificateName.of(PROJECT_ID, LOCATION, CA_poolId, CSR_CERTIFICATE_NAME) + .toString()); + + String pemCertificate = response.getPemCertificate(); + + privateca.ActivateSubordinateCa.activateSubordinateCa( + PROJECT_ID, LOCATION, CA_poolId, CA_NAME, SUBORDINATE_CA_NAME, pemCertificate); + assertThat(stdOut.toString()).contains("Current State: STAGED"); + } + } +}