The Lab will walk you through the following tasks:

This Codelab guides you through the hands-on experience of generating self-signed certificates and its deployment into the VHost object of Apigee Edge.

Even that this lab is tailored to an On-premises Edge installation, it is applicable to Apigee Cloud as well.

We assume that traininglab organization that has prod environment are provisioned and that two virtual hosts are created in the prod environment:

default

9001

traininglab-prod.apigee.net

secure

9005

api.traininglab.com

How will you use this tutorial?

Only read through it Read it and complete the exercises

How would you rate your experience with Google Cloud Platform?

Novice Intermediate Proficient

Setting UP CA Authority

You can define/create your CA authority on any of the systems, Linux/Unix or Windows.

The most trouble-free way to do it, is on your Linux box. I.e., Node 1, in the root home (~) directory.

If done on Windows, you are recommended to download and install openssl utility. You also need to have a Java SDK installed to have an access to jar utility.

Prerequisite for Windows: openssl utility; download it from https://indy.fulgan.com/SSL/openssl-1.0.2l-i386-win32.zip

1. CA admin: Create a directory edge-tls that will contains CA folders. In your project working folder, edge-tls, create folder rootca and go into it.

cd <your-working-folder>/edge-tls
mkdir rootca
cd rootca

2. CA admin: In the rootca folder, setup ca folders and serial numbers for certificates, crl, and init the index.db file.

mkdir ca
echo "1001" > ca/serial
echo "1001" > ca/crlnumber
touch ca/index.db
mkdir ca-certs

3. CA admin: Generate CA's private key.

openssl genrsa -aes256 -out ca/rootca-key.pem 2048

Pass phrase: MockServer123

4. CA admin: For a number of certificate-related operations, it is tedious to use command-line options. The .conf file eases the burden.

Create ca.conf file in the edge-tls/rootca folder with following contents:

dir = .

[ ca ]
default_ca              = root_ca

[ root_ca ]
database                = $dir/ca/index.db
serial                  = $dir/ca/serial
crlnumber               = $dir/ca/crlnumber
certificate             = $dir/ca-certs/rootca-crt.pem
private_key             = $dir/ca/rootca-key.pem
new_certs_dir           = $dir/ca-certs
default_days            = 365
default_md              = sha256
default_crl_days        = 30
email_in_dn             = no
unique_subject          = no
crl_extensions          = ca_crl_ext
x509_extensions         = ca_req_ext
policy                  = MatchingPolicy

[ req ]
default_bits            = 2048
encrypt_key             = no            # non-prod
default_md              = sha256
utf8                    = yes
string_mask             = utf8only
prompt                  = yes          # Prompt for DN input
distinguished_name      = ca_dn        # How to handle the distinguished name when requesting a certificate
x509_extensions         = ca_req_ext   # X.509 extensions to use when requesting a certificate

[ ca_dn ]
countryName                             = Country Name (2 letter code)
countryName_default                     = UK
stateOrProvinceName                     = State or Province Name (full name)
stateOrProvinceName_default             = England
localityName                            = Locality Name (eg, city)
localityName_default                    = Kingston
organizationName                        = Organization Name (eg, company)
organizationName_default                = Mock Server Ltd.
organizationalUnitName                  = Organizational Unit Name (eg, section)
organizationalUnitName_default          = Security Dept
commonName                              = Common Name
emailAddress                            = Contact email for this Certificate
emailAddress_default                    = admin@mockserver.com


[ MatchingPolicy ]
countryName             = match         # Must match CA's countryName
stateOrProvinceName     = optional      # optional input
localityName            = optional      # optional input
organizationName        = supplied      # Must supply organizationName
organizationalUnitName  = optional      # optional input
commonName              = supplied      # Must be supplied
emailAddress            = supplied      # supplied for contact purposes


[ ca_req_ext ]
basicConstraints = critical, CA:true
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
authorityInfoAccess = OCSP;URI:http://ocsp.mockserver.com:3000, caIssuers;URI:http://ocsp.mockserver.com:3000/rootCA.crt
crlDistributionPoints = URI:http://ocsp.mockserver.com:3000/rootCRL.crl

[ server_req_ext ]
basicConstraints = CA:FALSE
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectKeyIdentifier = hash
authorityInfoAccess = OCSP;URI:http://ocsp.mockserver.com:3000, caIssuers;URI:http://ocsp.mockserver.com:3000/rootCA.crt
crlDistributionPoints = URI:http://ocsp.mockserver.com:3000/rootCRL.crl

[ client_req_ext ]
basicConstraints = CA:FALSE
keyUsage = critical,digitalSignature
extendedKeyUsage = clientAuth
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
authorityInfoAccess = OCSP;URI:http://ocsp.mockserver.com:3000, caIssuers;URI:http://ocsp.mockserver.com:3000/rootCA.crt
crlDistributionPoints = URI:http://mockserver.com:3000/rootCA.crl

[ ca_crl_ext ]
authorityKeyIdentifier = keyid:always
authorityInfoAccess = caIssuers;URI:http://ocsp.mockserver.com:3000/rootCA.crt

[ ca_ocsp_ext ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always

5. CA admin: Using CA key, generate a CA certificate.

openssl req -config ca.conf -x509 -new -nodes -key ca/rootca-key.pem -out ca-certs/rootca-crt.pem -days 3650

...
Country Name (2 letter code) [UK]:
State or Province Name (full name) [England]:
Locality Name (eg, city) [Kingston]:
Organization Name (eg, company) [Mock Server Ltd.]:
Organizational Unit Name (eg, section) [Security Dept]:
Common Name []:mockserver.com
admin@mockserver.com [admin@mockserver.com]:

6. CA admin: Verify root CA certificate

openssl x509 -noout -text -in ca-certs/rootca-crt.pem

1. In the edge-tls/rootca directory folders for server key, request and certificates.

mkdir server
mkdir server-certs

2. Go to server folder.

cd server

3. Server Admin: Prepare .conf file contents for the server certificate, file server-api-traininglab.conf in the rootca folder:

[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C=UK
ST=Surrey
L=Guildford
O=Training Lab Ltd
OU=API Team
emailAddress=admin@traininglab.com
CN = traininglab.com

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = api.traininglab.com
DNS.2 = api.traininglab.co.uk

4. Server Admin: While in rootca, generate the key. Use password: TrainingLab2017

openssl genrsa -aes256 -out server/traininglab-key.pem 2048

5. Server Admin: Generate Certificate Signing Request, CSR.

openssl req -config server-api-traininglab.conf -key server/traininglab-key.pem -out server/traininglab-csr.pem -days 3650 -new -sha256

1. CA Admin: Inspect certificate, extract SANs for the following step.

openssl req -noout -text -in server/traininglab-csr.pem

2. CA Admin: Validate SAN names. Inspect extensions section.

       Requested Extensions:
            X509v3 Subject Alternative Name: 
                DNS:api.traininglab.com, DNS:api.traininglab.co.uk

3. CA Admin: Prepare configuration file to sign server request with required SAN section.

Clone ca.conf file to ca-san-traininglab.conf.

cp ca.conf ca-san-traininglab.conf

4. CA Admin: Add fragment to the end of section [ server_req_ext ] after the line with crlDistributionPoints setting:

subjectAltName = @alt_names

[ alt_names ]
DNS.1 = api.traininglab.com
DNS.2 = api.traininglab.co.uk

5. CA Admin: Perform sign operation.

openssl ca -config ca-san-traininglab.conf -extensions server_req_ext -in server/traininglab-csr.pem -out server-certs/traininglab-crt.pem

Enter the rootca-key.pem password MockServer123.

Say y to Sign the certificate? question.

Say y to 1 out of 1 certificate requests certified, commit? question.

1. Server Admin: Verify certificate

openssl x509 -noout -text -in server-certs/traininglab-crt.pem

Notice in the output:

        X509v3 extensions:
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication

            X509v3 Subject Alternative Name: 
                DNS:api.traininglab.com, DNS:api.traininglab.co.uk

2. Server Admin: Verify chain of trust

openssl verify -CAfile ca-certs/rootca-crt.pem server-certs/traininglab-crt.pem 

server-certs/traininglab-crt.pem: OK

1. Make a folder for a jar file server-certs/traininglabKeystore

2. Go to the folder

3. In the folder, create: sub-folder META-INF

4. Concatenate whole certificate chain server-certs/traininglab-crt.pem and ca-certs/rootca-crt.pem into traininglab-crt-chain.pem file

cat server-certs/traininglab-crt.pem ca-certs/rootca-crt.pem > server-certs/traininglabKeystore/traininglab-crt-chain.pem

5. Copy the server/traininglab-key.pem in this folder.

6. In the META-INF create the descriptor.properties file and add following lines:

certFile=traininglab-crt-chain.pem
keyFile=traininglab-key.pem

7. Inside the traininglabKeystore folder run commands

jar -cf traininglabKeystore.jar traininglab-crt-chain.pem traininglab-key.pem 
jar -uf traininglabKeystore.jar META-INF/descriptor.properties

The contents of the traininglabKeyStore folder should look like:

1. Configure the contents of ~/.netrc file so that you can use -n curl option

Enter use IP of your MS node, email and password of Edge administrator.

machine 52.55.223.129 login admin@exco.com password Apigee123!

2. Verify that you can execute MS Management API calls by fetching the list of planet organisations.

$ curl -n http://10.132.0.9:8080/v1/o 

[ "VALIDATE", "org" ]

1. Create the keystore object

curl -H "Content-Type: text/xml" http://52.55.223.129:8080/v1/o/traininglab/environments/prod/keystores -d "<KeyStore name=\"traininglab\"/>" -n

Output:

{
  "certs" : [ ],
  "keys" : [ ],
  "name" : "traininglab"
}

2. Validate that the keystore object is created.

curl http://52.55.223.129:8080/v1/o/traininglab/environments/prod/keystores -n

Output:

[ "traininglab" ]

3. Upload a JAR file to a Keystore API

curl -X POST -H "Content-Type: multipart/form-data" -F file="@traininglabKeystore.jar" "http://52.55.223.129:8080/v1/o/traininglab/environments/prod/keystores/traininglab/keys?alias=traininglab-vhost&password=TrainingLab2017" -n

4. Verify the keystore

curl http://52.55.223.129:8080/v1/o/traininglab/environments/prod/keystores/traininglab -n

Output:

{
  "certs" : [ "traininglab-vhost-cert" ],
  "keys" : [ "traininglab-vhost" ],
  "name" : "traininglab"
}

1. Create Virtual Host using Management API command.

curl -n -X POST  -H "Content-Type: application/json" -d '{
  "hostAliases": [
    "api.traininglab.com"
  ],
  "interfaces": [],
  "name": "secure",
  "port": "9005",
  "sSLInfo": {
    "ciphers": [],
    "clientAuthEnabled": "false",
    "enabled": "true",
    "ignoreValidationErrors": false,
    "keyAlias": "traininglab-vhost",
    "keyStore": "traininglab",
    "protocols": []
  }
}' "http://52.55.223.129:8080/v1/organizations/traininglab/environments/prod/virtualhosts"

Output:

{
  "hostAliases" : [ "api.traininglab.com" ],
  "interfaces" : [ ],
  "listenOptions" : [ ],
  "name" : "secure",
  "port" : "9005",
  "sSLInfo" : {
    "ciphers" : [ ],
    "clientAuthEnabled" : "false",
    "enabled" : "true",
    "ignoreValidationErrors" : false,
    "keyAlias" : "traininglab-vhost",
    "keyStore" : "traininglab",
    "protocols" : [ ]
  }
}

2. Verify training lab keystore configuration using Edge UI.

Navigate to Admin/TLS Certificates

3. Verify Secure Virtual Host configuration using Edge UI.

Navigate to APIs/Environment Configuration, Virtual Hosts. Click on Show of secure VHost.

1. Using APIs/API Proxies, open Echo proxy editor.

2. Switch to DEVELOP tab.

3. Verify that the PreFlow event of the default Proxy Endpoint is active.

4. Using XML Editor, add <VirtualHost>secure</VirtualHost> element to the end of the <HTTPProxyConnection/> element

5. Press the Save button. Confirm to Save Revision dialog.

6. Click on the OVERVIEW tab and verify that Echo proxy is deployed into correct virtual hosts.

1. For TLS-enables endpoints, we cannot use IP address as a hostname. Add router's public IP address on your node 1 to the /etc/hosts file

34.207.96.3 api.traininglab.com

2. Check the connection, run ping api.traininglab.com

$ ping api.traininglab.com
PING api.traininglab.com (34.207.96.3): 56 data bytes
64 bytes from 34.207.96.3: icmp_seq=0 ttl=64 time=0.047 ms
64 bytes from 34.207.96.3: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from 34.207.96.3: icmp_seq=2 ttl=64 time=0.150 ms
^C

1. Try to run curl command to the /echo endpoint "as is", i.e., without any certificates. IF your root certificate is not trusted on a system level, then you will see:

$ curl -v https://api.traininglab.com:9005/echo
*   Trying 34.207.96.3...
* TCP_NODELAY set
* Connected to api.traininglab.com (34.207.96.3) port 9005 (#0)
* SSL certificate problem: Invalid certificate chain
* Curl_http_done: called premature == 1
* Closing connection 0
curl: (60) SSL certificate problem: Invalid certificate chain
More details here: https://curl.haxx.se/docs/sslcerts.html

2. Provide trust certificate chain to validate our server certificate.

$ curl --cacert ca-certs/rootca-crt.pem -v https://api.traininglab.com:9005/echo


*   Trying 34.207.96.3...
* TCP_NODELAY set
* Connected to api.traininglab.com (34.207.96.3) port 9005 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: traininglab.com
* Server certificate: mockserver.com
> GET /echo HTTP/1.1
> Host: api.traininglab.com:9005
> User-Agent: curl/7.51.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sat, 02 Dec 2017 04:09:06 GMT
< Content-Length: 0
< Connection: keep-alive
< Host: api.traininglab.com:9005
< X-Forwarded-For: 86.134.79.188
< X-Forwarded-Port: 9005
< X-Forwarded-Proto: https
< User-Agent: curl/7.51.0
< Accept: */*
< Server: Apigee Router
< 
* Curl_http_done: called premature == 0
* Connection #0 to host api.traininglab.com left intact
bash-3.2$ 

1. Using Chrome, try to hit the echo proxy.

Configuring Machine to Trust the Self-Signed Certificate

Mac OSX: Using Apple Keychain Access to register CA Trust certificate

1. Open Keychain Access utility (Cmd+Space, keychain...)

2. Select System Keychain on the left.

3. Select File/Import Items...

4. Select 'our company's chain trust, rootca-crt.pem file and Press Open button.

5. Type your password to allow the operation. Click Modify keychain button.

6. Double-click imported certificate; Open Trust sub-tree and change When Using this certificate combo-box item to Always Trust.

7. Close the window and confirm your password. Click Update Settings button.

Windows OS: Using Certificate Manager MMC snap-in to register CA Trust certificate

1. To access Certificate Manager, click the Start button, type certmgr.msc in the search field, and click the Enter key.

2. Right-click Trusted Root Certification Authorities

3. In menu select All Tasks, Import...

4. Click Browse...

5. Change type to all Files navigate to the ca-certs/rootca.pem

6. Click Open. Press Next.

7. For Place all certificates in the following folder, click Browse... Chose Trusted Root Certification Authorities. Click OK

8. Press Next and Finish.

9. Important: This is a dialog that you agree that your computer Certificate Manager will trust any certificates, signed by this CA certificate. Click Yes.

From now on any certificate signed by our CA will be trusted on this computer.

Validating SSC in OS using Chrome

1. Using Chrome when our root ca certificate is 'Always Trusted:

2. We can display and validate a certificate presented by a server using following openssl command:

openssl s_client -showcerts -connect 34.207.96.3:9005 -CAfile rootca-crt.pem </dev/null