Skip to content

Commit

Permalink
changes output in CLI to unify returned ID's from providers in Cloud …
Browse files Browse the repository at this point in the history
…ID. Provides ability to provider ARN as well adds ARN flag in CLI. Adds AWS Cloud Provider testing for provisioning in cucumber tests and also refactors code accordingly. Adds AWS client to delete certificate after certificate is provisioned afterward
  • Loading branch information
luispresuelVenafi committed Jun 5, 2024
1 parent 38f28d3 commit ab03020
Show file tree
Hide file tree
Showing 16 changed files with 175 additions and 62 deletions.
5 changes: 3 additions & 2 deletions README-CLI-CLOUD.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,16 @@ Options:

| Command | Description |
|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `--arn` | Use to specify AWS Resource Name which provisioned certificate will replace (only for AWS Certificate Manager) |
| `--certificate-id` | The id of the certificate to be provisioned to a cloud keystore. |
| `--certificate-id-file` | Use to specify a file name that contains the unique identifier of the certificate. Required when `--certificate-id` is not specified. |
| `--certificate-name` | Use to specify Cloud Keystore Certificate Name if it supports it |
| `--certificate-name` | Use to specify Cloud Keystore Certificate Name to be set or replaced by provisioned certificate (only for Azure Key Vault and Google Certificate Manager) |
| `--file` | Use to specify a file name and a location where the output should be written. Example: --file /path-to/provision-output |
| `--format` | The format of the operation output: text or JSON. Defaults to text. |
| `--keystore-id` | The id of the cloud keystore where the certificate will be provisioned. |
| `--keystore-name` | The name of the cloud keystore where the certificate will be provisioned. Must be set along with provider-name flag. |
| `--pickup-id-file` | Use to specify a file name that contains the unique identifier of the certificate returned by the enroll or renew actions if --no-pickup was used or a timeout occurred. Required when `--pickup-id` is not specified. |
| `--pickup-id` | Use to specify the unique identifier of the certificate returned by the enroll or renew actions. Required when `--pickup-id-file` is not specified. |
| `--pickup-id-file` | Use to specify a file name that contains the unique identifier of the certificate returned by the enroll or renew actions if --no-pickup was used or a timeout occurred. Required when `--pickup-id` is not specified. |
| `--provider-name` | The name of the cloud provider which owns the cloud keystore where the certificate will be provisioned. Must be set along with keystore-name flag. |

## Parameters for Applying Certificate Policy
Expand Down
1 change: 1 addition & 0 deletions aruba/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ MAINTAINER Venafi DevOps Integrations <opensource@venafi.com>

RUN gem install aruba json_spec
RUN gem install google-cloud-certificate_manager-v1
RUN gem install aws-sdk-acm
COPY . /vcert/
ENV BUNDLE_PATH="/vcert/tpp"
ENV GCP_AUTH_PATH="/vcert/cloud_providers"
Expand Down
8 changes: 7 additions & 1 deletion aruba/cucumber.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ RUN_COMMAND="docker run -t --rm \
-e GCP_REGION \
-e GCP_PROVIDER_NAME \
-e GCP_KEYSTORE_NAME \
-e GCP_KEYSTORE_ID"
-e GCP_KEYSTORE_ID \
-e AWS_ACCESS_KEY_ID \
-e AWS_REGION \
-e AWS_SECRET_ACCESS_KEY \
-e AWS_PROVIDER_NAME \
-e AWS_KEYSTORE_NAME \
-e AWS_KEYSTORE_ID"

# Use getopts to handle command-line options
while getopts "a:b:" opt; do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,38 @@ Feature: provision to cloud keystore
And I remember the output
And I use previous Pickup ID to provision from VCP a certificate to cloudkeystore "<cloudkeystore>" setting keystore and provider names
And I remember the output
And it should output cloud ID
And I grab cloud ID from output
Then I clean up previous installed certificate from cloudkeystore
Examples:
| cloudkeystore |
| GOOGLE |
| AWS |

Scenario Outline: Enroll certificate and execute provisioning for cloud keystore and get output in JSON
Given I enroll a random certificate with defined platform VCP with -csr service -no-prompt
And I remember the output
And I use previous Pickup ID to provision from VCP a certificate to cloudkeystore "<cloudkeystore>" setting keystore and provider names with -format json
And I remember the output
And it should output cloud ID in JSON
And I grab cloud ID from JSON output
Then I clean up previous installed certificate from cloudkeystore
Examples:
| cloudkeystore |
| GOOGLE |
| AWS |

Scenario Outline: Enroll certificate, execute provisioning and then provisioning again for replace
Given I enroll a random certificate with defined platform VCP with -csr service -no-prompt
And I remember the output
And I use previous Pickup ID to provision from VCP a certificate to cloudkeystore "<cloudkeystore>" setting keystore and provider names
And I remember the output
And the output should contain "cloudId:"
And the output should contain "machineIdentityActionType: New"
And I grab cloud ID from output
Then I use previous Pickup ID and cloud ID to provision again
And I remember the output
And the output should contain the previous cloud ID
And the output should contain "machineIdentityActionType: ReProvision"
Then I clean up previous installed certificate from cloudkeystore
Examples:
| cloudkeystore |
| AWS |
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,23 @@
steps %{Then I try to run `#{cmd}`}
end

And(/^I use previous Pickup ID and cloud ID to provision again$/) do
keystore_provider_names = true
flags = ""
if @cloudkeystore_type == $keystore_type_aws
flags += " -arn #{@cloud_id}"
elsif @cloudkeystore_type == $keystore_type_azure or @cloudkeystore_type == $keystore_type_gcp
flags += " -certificate-name #{@cloud_id}"
end
flags += @global_set_provision_flags
cmd = build_provision_cmd($platform_vcp, @cloudkeystore_type, keystore_provider_names, flags)
steps %{Then I try to run `#{cmd}`}
end

def build_provision_cmd(platform, cloudkeystore_type, keystore_provider_names, flags = "")

@global_set_provision_flags = flags

platform_flag = " -platform " + platform

cmd = "vcert provision cloudkeystore #{platform_flag} #{ENDPOINTS[$platform_vcp]} -pickup-id #{@pickup_id}"
Expand All @@ -22,7 +37,14 @@ def build_provision_cmd(platform, cloudkeystore_type, keystore_provider_names, f
provider_name = ""
keystore_id = ""
case cloudkeystore_type
when $keystore_type_azure
when $keystore_type_aws
if keystore_provider_names
keystore_name = $aws_keystore_name
provider_name = $aws_provider_name
@cloudkeystore_type = $keystore_type_aws
else
keystore_name = $aws_keystore_id
end
when $keystore_type_gcp
if keystore_provider_names
keystore_name = $gcp_keystore_name
Expand Down Expand Up @@ -51,45 +73,75 @@ def build_provision_cmd(platform, cloudkeystore_type, keystore_provider_names, f
return cmd
end

Then(/^it should output cloud ID( in JSON)?$/) do |json|
Then(/^I grab cloud ID from( JSON)? output$/) do |json|

@cloud_id = get_cloud_id_from_output(json)

end

def get_cloud_id_from_output(json = false)
if @previous_command_output.nil?
fail(ArgumentError.new('@previous_command_output is nil'))
end

Kernel.puts("Checking output:\n"+@previous_command_output)
cloud_id = ""
case @cloudkeystore_type
when $keystore_type_aws
when $keystore_type_azure
when $keystore_type_gcp
cloud_id = "gcpId"
else
fail(ArgumentError.new("Unexpected : #{@cloudkeystore_type}"))
end
cloud_id_attr = "cloudId:"

if json
json_string = extract_json_from_output(@previous_command_output)
JSON.parse(json_string)
@cloud_id = unescape_text(normalize_json(json_string, "#{cloud_id}")).tr('"', '')
cloud_id = unescape_text(normalize_json(json_string, "#{cloud_id_attr}")).tr('"', '')
else
m = @previous_command_output.match /#{cloud_id} (.+)$/
@cloud_id = m[1]
m = @previous_command_output.match /#{cloud_id_attr} (.+)$/
cloud_id = m[1]
end
cloud_id
end

Then(/^the output( in JSON)? should contain the previous cloud ID$/) do |json|
old_cloud_id = @cloud_id
new_cloud_id = get_cloud_id_from_output(json)
if old_cloud_id != new_cloud_id
cleanup_keystore(old_cloud_id)
cleanup_keystore(new_cloud_id)
fail(ArgumentError.new("Expected old Cloud ID: #{old_cloud_id} to be same as new Cloud ID, but got: #{new_cloud_id}"))
end
end

And(/^I clean up previous installed certificate from cloudkeystore/) do ||
cleanup_keystore
end

def cleanup_keystore(cloud_id = "")
case @cloudkeystore_type
when $keystore_type_aws
cleanup_aws(cloud_id)
when $keystore_type_azure
when $keystore_type_gcp
cleanup_google
cleanup_google(cloud_id)
else
fail(ArgumentError.new("Unexpected : #{@cloudkeystore_type}"))
end
end

def cleanup_google
client = create_certificate_manager_client
certificate_name = "projects/#{ENV['GCP_PROJECT']}/locations/#{ENV['GCP_REGION']}/certificates/#{@cloud_id}"
delete_certificate(client, certificate_name)
def cleanup_google(cloud_id = "")
client = create_google_certificate_manager_client
if cloud_id
certificate_name = "projects/#{ENV['GCP_PROJECT']}/locations/#{ENV['GCP_REGION']}/certificates/#{cloud_id}"
else
certificate_name = "projects/#{ENV['GCP_PROJECT']}/locations/#{ENV['GCP_REGION']}/certificates/#{@cloud_id}"
end

delete_gcm_certificate(client, certificate_name)
end

def cleanup_aws(cloud_id = "")
client = create_aws_certificate_manager_client
if cloud_id
certificate_arn = cloud_id
else
certificate_arn = @cloud_id
end

delete_acm_certificate(client, certificate_arn)
end
4 changes: 4 additions & 0 deletions aruba/features/support/aruba.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
$gcp_keystore_name = ENV["GCP_KEYSTORE_NAME"]
$gcp_provider_name = ENV["GCP_PROVIDER_NAME"]

$aws_keystore_id = ENV["AWS_KEYSTORE_ID"]
$aws_keystore_name = ENV["AWS_KEYSTORE_NAME"]
$aws_provider_name = ENV["AWS_PROVIDER_NAME"]

def last_json
last_command_started.stdout.to_s
end
Expand Down
20 changes: 20 additions & 0 deletions aruba/features/support/aws_provider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'aws-sdk-acm'

# Initialize the Certificate Manager Client
def create_aws_certificate_manager_client
Aws::ACM::Client.new(
region: ENV['AWS_REGION'],
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
)
end

# Delete a certificate
def delete_acm_certificate(client, certificate_arn)
begin
client.delete_certificate({ certificate_arn: certificate_arn })
puts "Certificate with ARN #{certificate_arn} deleted successfully."
rescue Aws::ACM::Errors::ServiceError => e
puts "Error deleting certificate: #{e.message}"
end
end
4 changes: 2 additions & 2 deletions aruba/features/support/google_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
ENV['GOOGLE_APPLICATION_CREDENTIALS'] = ENV['GCP_AUTH_PATH']

# Initialize the Certificate Manager Client
def create_certificate_manager_client
def create_google_certificate_manager_client
Google::Cloud::CertificateManager::V1::CertificateManager::Client.new
end

# Delete a certificate
def delete_certificate(client, certificate_name)
def delete_gcm_certificate(client, certificate_name)
request = Google::Cloud::CertificateManager::V1::DeleteCertificateRequest.new(
name: certificate_name
)
Expand Down
1 change: 1 addition & 0 deletions cmd/vcert/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ type commandFlags struct {
providerName string
keystoreName string
keystoreCertName string
keystoreARN string
provisionOutputFile string
provisionPickupID string
provisionFormat string
Expand Down
7 changes: 3 additions & 4 deletions cmd/vcert/cmdCloudKeystores.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,20 @@ func doCommandProvisionCloudKeystore(c *cli.Context) error {
MachineIdentityId: metadata.MachineIdentityID,
MachineIdentityActionType: metadata.MachineIdentityActionType,
}
result.CloudID = metadata.CertificateID
switch metadata.CloudKeystoreType {
case domain.CloudKeystoreTypeACM:
result.ARN = metadata.CertificateID
// do nothing
case domain.CloudKeystoreTypeAKV:
result.AzureID = metadata.CertificateID
result.AzureName = metadata.CertificateName
result.AzureVersion = metadata.CertificateVersion
case domain.CloudKeystoreTypeGCM:
result.GcpID = metadata.CertificateID
result.GcpName = metadata.CertificateName
default:
return fmt.Errorf("unknown keystore metadata type: %s", metadata.CloudKeystoreType)
}

err = result.Flush(flags.provisionFormat, flags.provisionOutputFile)
err = result.Flush(flags.provisionFormat, flags.provisionOutputFile, metadata.CloudKeystoreType)
if err != nil {
return fmt.Errorf("failed to output the results: %s", err)
}
Expand Down
19 changes: 13 additions & 6 deletions cmd/vcert/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -741,10 +741,16 @@ var (

flagKeystoreCertName = &cli.StringFlag{
Name: "certificate-name",
Usage: "Use to specify Cloud Keystore Certificate Name if it supports it",
Usage: "Use to specify Cloud Keystore Certificate Name to be set or replaced by provisioned certificate (only for Azure Key Vault and Google Certificate Manager)",
Destination: &flags.keystoreCertName,
}

flagKeystoreARN = &cli.StringFlag{
Name: "arn",
Usage: "Use to specify AWS Resource Name which provisioned certificate will replace (only for AWS Certificate Manager)",
Destination: &flags.keystoreARN,
}

flagProvisionOutputFile = &cli.StringFlag{
Name: "file",
Usage: "Use to specify a file name and a location where the output should be written. " +
Expand Down Expand Up @@ -906,16 +912,17 @@ var (
provisionFlags = flagsApppend(
credentialsFlags,
flagPlatform,
flagKeystoreARN,
flagCertificateID,
flagCertificateIDFile,
flagKeystoreCertName,
flagProvisionOutputFile,
flagProvisionFormat,
flagKeystoreID,
flagKeystoreName,
flagProvisionPickupID,
flagPickupIDFile,
flagKeystoreCertName,
flagProviderName,
flagKeystoreName,
flagKeystoreID,
flagProvisionFormat,
flagProvisionOutputFile,
)

commonCredFlags = []cli.Flag{flagConfig, flagProfile, flagUrl, flagToken, flagTrustBundle}
Expand Down
Loading

0 comments on commit ab03020

Please sign in to comment.