Update certificate generation documentation
This commit is contained in:
Родитель
3d2a719c20
Коммит
3c9c997d07
|
@ -2,75 +2,54 @@
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
The Bridge has an endpoint that allows the generation of certificates for test purposes. The Bridge generates the following types of certs on demand:
|
In order to test certificate-based security scenarios, we generate test certificates for:
|
||||||
|
|
||||||
* Root Certificate Authority (CA)
|
* Root Certificate Authority (CA)
|
||||||
* Machine certificate
|
* Machine certificate
|
||||||
* Certificate Revocation List (CRL)
|
* Certificate Revocation List (CRL)
|
||||||
|
|
||||||
When the bridge is running in single machine mode (i.e., Bridge and tests are running on the same machine), the Bridge is responsbile for installing and removing certificates from the test machine.
|
This happens using the CertificateGenerator tool, located at `src/System.Private.ServiceModel/tools/CertificateGenerator`
|
||||||
|
|
||||||
When the bridge is running in multi-machine mode (i.e., Bridge is running with `-allowRemote`, and tests are running on another machine), the Bridge will install certificates the CA and machine certificate on the Bridge host machine, and the Bridge client will install and remove the machine certificates on the client side.
|
This tool is automatically called on the following occasions:
|
||||||
|
|
||||||
The Bridge implements certificate generation as a series of endpoints modelled as "Resources". A Resource is any type that implementes the IResource interface - for example, each endpoint available to test is modelled as a Resource.
|
* Creating a WCF IIS Hosted Service using `SetupWcfIISHostedService.cmd`
|
||||||
|
* Starting a WCF Self Hosted Service using `StartWCFSelfHostedSvc.cmd`
|
||||||
|
* Running `RefreshServerCertificates.cmd`
|
||||||
|
|
||||||
Parameters are passed to/from the endpoints as JSON key-value pairs.
|
Certificate generation happens using the CertificateGenerator tool, Certificate generation happens only on Windows machines
|
||||||
|
|
||||||
|
Upon calling, the CertificateGenerator generates the following certificates:
|
||||||
|
|
||||||
## Settings on Bridge initialization
|
* Root Certificate
|
||||||
|
* Client certificate
|
||||||
|
* Machine certificates
|
||||||
|
* localhost
|
||||||
|
* machine name
|
||||||
|
* machine fully qualified domain name
|
||||||
|
* revoked certificate
|
||||||
|
* expired certificate
|
||||||
|
* with server alt names
|
||||||
|
|
||||||
* `TestRootCertificatePassword` - string - password for certificates generated/exported. Default is "test"
|
The certificate revocation list is published to (by default) C:\wcftest\test.crl, and can be changed via app.config
|
||||||
* `TestRootCertificateValidityPeriod` - TimeSpan - valid timespan for certificates generated. Default is 24 hours
|
|
||||||
|
|
||||||
|
Certificates expire in 90 days
|
||||||
|
|
||||||
## Resources exposed
|
The CA certificates get installed into the machine trusted certificate store
|
||||||
|
Machine certificates get installed into the machine My store
|
||||||
|
|
||||||
### Certificate Authority Resource
|
## Certificate revocation list
|
||||||
|
|
||||||
name: `WcfService.CertificateResources.CertificateAuthorityResource`
|
A certificate revocation list is generated every time certificates are generated; the CRL is valid for the duration of the CA certificate.
|
||||||
|
|
||||||
|HTTP Verb|Action|
|
Each certificate generated has a CRL Distribution Point of _base_address_/Crl - this is automatically set up when run using the scripts above, but if not using the scripts, then the endpoint need to be set up accordingly so that the CRL can be accessed. If this is not set up, certificates may fail to validate due to the CRL being inaccessible
|
||||||
|---------|------|
|
|
||||||
|`PUT`| Creates a root CA certificate <br/> Parameters: none <br/> Returns: `thumbprint` - thumbprint of the root CA <br/> *Note: This PUT doesn't need to be issued as this is initialized automatically as part of any other PUT/GET action on all \*CertificateResources.* <br/> |
|
|
||||||
|`GET`| Retrieves the Root CA certificate from the Bridge <br/> Returns: `thumbprint` - thumbprint of the Root CA, `certificate` - Base64 encoded X509 Certificate |
|
|
||||||
|
|
||||||
### Machine Certificate Resource
|
|
||||||
|
|
||||||
name: `WcfService.CertificateResources.MachineCertificateResource`
|
|
||||||
|
|
||||||
|HTTP Verb|Action|
|
|
||||||
|---------|------|
|
|
||||||
|`PUT`| Creates a machine certificate <br/> Parameters: `subject` - comma-separated list of subject names (the first subject will be the CN of the certificate; all others will be listed as DNS Subject Alternative Names) <br/> Returns: `thumbprint` - thumbprint of the machine certificate; `isLocal` - if the certificate was generated for a machine name local to the Bridge |
|
|
||||||
|`GET`| No parameters <br/> Returns: `subjects` - list of certificate subjects; `thumbprints` - corresponding list of certificate thumbprints |
|
|
||||||
|`GET`| Retrieves the certificate with a given `subject` or `thumbprint` from the Bridge <br/> Parameters: `thumbprint` - thumbprint of the certificate; OR `subject` - subject name of the cert to retrieve. If both are specified, `thumbprint` takes precedence <br/> Returns: `thumbprint` - thumbprint of the certificate, `certificate` - Base64 encoded X509 Certificate |
|
|
||||||
|
|
||||||
### User Certificate Resource
|
|
||||||
|
|
||||||
name: `WcfService.CertificateResources.UserCertificateResource`
|
|
||||||
|
|
||||||
|HTTP Verb|Action|
|
|
||||||
|---------|------|
|
|
||||||
|`PUT`| Creates a user certificate <br/> Parameters: `subject` - comma-separated list of subject names (the first subject will be the CN of the certificate; all others will be listed as Principal Names in the Subject Alternative Name field) <br/> Returns: `thumbprint` - thumbprint of the user certificate |
|
|
||||||
|`GET`| Same as `MachineCertificateResource`. At the moment, the MachineCertificateResource and UserCertificateResource caches are the same, so issuing a GET to either one will retrieve the machine or user cert, agnostic of the cert type. |
|
|
||||||
|
|
||||||
### Certificate Revocation List Resource
|
|
||||||
|
|
||||||
name: `WcfService.CertificateResources.CertificateRevocationListResource`
|
|
||||||
|
|
||||||
|HTTP Verb|Action|
|
|
||||||
|---------|------|
|
|
||||||
|`PUT`| No parameters <br/> Creates a Certificate Revocation List <br/> Returns: `revokedCertificates` - comma-separated list of revoked certificate serial numbers |
|
|
||||||
|`PUT`| Parameters: `revoke` - serial number of the certificate to revoke <br/> Returns: `revokedCertificates` - comma-separated list of revoked certificate serial numbers|
|
|
||||||
|`GET`| Retrieves the CRL from the Bridge as an application/octet-stream <br/> *Not returned as a JSON key-val pair* |
|
|
||||||
|
|
||||||
Note that for the certificate revocation list `GET` action, the return value is the raw Certificate Revocation List. All certs created will list */resource/WcfService.CertificateResources.CertificateRevocationListResource* as the CRL distribution point.
|
|
||||||
|
|
||||||
## Usage pattern
|
|
||||||
|
|
||||||
The expected usage pattern is to first `PUT` to the requested resource, followed by `GET`ting the resource. Some resources allow the use of `GET` without `PUT`, but it's recommended to follow this practice in case future changes enforce the `PUT`-then-`GET` semantic.
|
|
||||||
|
|
||||||
## Certificate validity
|
## Certificate validity
|
||||||
|
|
||||||
The default validity period of certificates generated is 24 hours. In order to deal with potential time skew, certificates are valid for one hour *prior* to the generation time of the certificate.
|
The default validity period of certificates generated is 90 days. In order to deal with potential time skew, certificates are valid for five minutes *prior* to the generation time of the certificate.
|
||||||
|
|
||||||
|
## Certificate refresh
|
||||||
|
|
||||||
|
Certificates must be refreshed at the end of the certificate expiry - there is no provision for extension of the certificate validity date.
|
||||||
|
|
||||||
|
`RefreshServerCertificates.cmd` can be set up as a scheduled task to automatically perform these functions
|
||||||
|
|
||||||
Certificate Revocation Lists have a "Next Update" field of two minutes after the request time. This helps with time skew issues when testing cross machines. This does mean, however, that Windows will not check the CRL again until the "Next Update" time is hit, which may result in oddness when testing CRL revocation.
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
Manual Tests Instruction
|
Manual Tests Instruction
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
@ -13,26 +14,18 @@ Tests:
|
||||||
Https_ClientCredentialTypeTests.BasicAuthentication_RoundTrips_Echo
|
Https_ClientCredentialTypeTests.BasicAuthentication_RoundTrips_Echo
|
||||||
```
|
```
|
||||||
|
|
||||||
The WCF Test Root CA certificate need to be retrieved from the Bridge and installed on the local machine before tests can be run
|
The WCF Test Root CA certificate need to be retrieved from the server and installed on the local machine before tests can be run. This is automatically done when running build.sh / build.cmd.
|
||||||
|
|
||||||
Requirements:
|
When running build.sh on a Linux machine, ensure that the user has permission to run the `InstallRootCertificate.sh` script with sudo (i.e., the user is listed in the sudoers file). For best results, add the following to the sudoers file
|
||||||
|
```
|
||||||
* Requires a Windows machine running the Bridge
|
user ALL=(ALL) NOPASSWD:ALL
|
||||||
|
```
|
||||||
Assumes:
|
see the _visudo_ man page for details on how to do this
|
||||||
|
|
||||||
* ${GitWcfRoot} is the root of the WCF Core git repo
|
|
||||||
* ${BridgeHost} is the Bridge host machine name
|
|
||||||
|
|
||||||
Steps:
|
Steps:
|
||||||
|
|
||||||
1. Ensure the Bridge is running on a Windows machine with remote access allowed: `startBridge.cmd -allowRemote` <br/>
|
1. Ensure the service is running
|
||||||
If running Bridge on a machine not on the same subnet as the test client machine: `startBridge.cmd -allowRemote -remoteAddresses:*`
|
2. On Linux, go to ${GitWcfRoot} and run `./build.sh -p:WithCategories=OuterLoop -p:ServiceUri=your-service-uri -p:`
|
||||||
2. On Linux, go to ${GitWcfRoot} and run `./build.sh`
|
|
||||||
3. On Linux, `pushd ${GitWcfRoot}/src/System.Private.ServiceModel/tools/setupfiles`
|
|
||||||
4. Install the certificate file `sudo ./TestRootCertificateInstaller.sh --service-host ${ServiceHost} --cert-file ~/tmp/wcfca.crt`. Note that the --cert-file should be a file in the the user tmp directory and the filename must have a .crt extension
|
|
||||||
5. Specify the Bridge host location `export BridgeHost=${BridgeHost}`
|
|
||||||
6. Run tests as needed, such as with `${GitWcfRoot}/build.sh /p:WithCategories=OuterLoop`
|
|
||||||
|
|
||||||
**Linux: NegotiateStream tests with ambient credentials**
|
**Linux: NegotiateStream tests with ambient credentials**
|
||||||
|
|
||||||
|
@ -52,15 +45,16 @@ Tests:
|
||||||
NegotiateStream_Http_Tests.NegotiateStream_Http_AmbientCredentials
|
NegotiateStream_Http_Tests.NegotiateStream_Http_AmbientCredentials
|
||||||
|
|
||||||
```
|
```
|
||||||
|
The self-hosted WCF Service or IIS Hosted service must be running under a LOCAL SYSTEM context
|
||||||
|
|
||||||
|
Furthermore, the WCF Test Root CA certificate needs to be retrieved from the service and installed on the local machine before tests can be run - this is automatically done when running tests if the user has the ability to run scripts as a superuser (sudo)
|
||||||
|
|
||||||
The WCF Test Root CA certificate need to be retrieved from the Bridge and installed on the local machine before tests can be run.
|
|
||||||
In addition, the Bridge must be running under a LOCAL SYSTEM context
|
|
||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
|
|
||||||
* Requires a Windows machine running the Bridge
|
* Requires a Windows machine running the WCF test service
|
||||||
* The Windows machine should be on a Windows domain
|
* * The Windows machine should be on a Windows domain
|
||||||
* A tool such as `psexec` is needed to start the Bridge as LOCAL SYSTEM. <br/>
|
* If using the self-hosted service (as opposed to the IIS-hosted service), a tool such as `psexec` is needed to start the self-hosted service as LOCAL SYSTEM.
|
||||||
Download the tool from https://technet.microsoft.com/en-us/sysinternals/psexec.aspx <br />
|
Download the tool from https://technet.microsoft.com/en-us/sysinternals/psexec.aspx <br />
|
||||||
`psexec -s -h <command>` will start a command as an elevated LOCAL SYSTEM user
|
`psexec -s -h <command>` will start a command as an elevated LOCAL SYSTEM user
|
||||||
|
|
||||||
|
@ -77,7 +71,7 @@ Assumes:
|
||||||
_Note: The domain controller FQDN must be in uppercase_
|
_Note: The domain controller FQDN must be in uppercase_
|
||||||
|
|
||||||
* ${GitWcfRoot} : root of the WCF Core git repo
|
* ${GitWcfRoot} : root of the WCF Core git repo
|
||||||
* ${BridgeHost} : Bridge host machine name
|
* ${ServiceUri} : WCF Service URI
|
||||||
* ${NegotiateTestRealm} : Kerberos realm on which server is running
|
* ${NegotiateTestRealm} : Kerberos realm on which server is running
|
||||||
* ${NegotiateTestUserName} : Valid user name on Kerberos realm specified by ${NegotiateTestRealm}
|
* ${NegotiateTestUserName} : Valid user name on Kerberos realm specified by ${NegotiateTestRealm}
|
||||||
* ${NegotiateTestPassword} : User's password on the Kerberos realm
|
* ${NegotiateTestPassword} : User's password on the Kerberos realm
|
||||||
|
@ -119,17 +113,27 @@ On RedHat/CentOS: (to be investigated)
|
||||||
|
|
||||||
Steps:
|
Steps:
|
||||||
|
|
||||||
1. Ensure the Bridge is running on a Windows machine and as LOCAL SYSTEM with `psexec -s -h ${GitWcfRoot}\startBridge.cmd -allowRemote -remoteAddresses:*`
|
1. Ensure the service is running on a Windows machine - either IIS hosted or self-hosted
|
||||||
2. On Linux, go to ${GitWcfRoot} and run `./build.sh`
|
2. On Linux, go to ${GitWcfRoot} and run `./build.sh /p:WithCategories=OuterLoop` to do a run and install the certificates
|
||||||
3. On Linux, `pushd $(GitWcfRoot)/src/System.Private.ServiceModel/tools/setupfiles`
|
3. Initialize Kerberos by running `kinit ${NegotiateTestUserName}@${NegotiateTestRealm}`; enter the password for the user, ${NegotiateTestPassword}
|
||||||
4. Install the certificate file `sudo ./TestRootCertificateInstaller.sh --service-host ${ServiceHost} --cert-file ~/tmp/wcfca.crt`. Note that the --cert-file should be a file in the the user tmp directory and the filename must have a .crt extension
|
4. Run `klist` to see that the Kerberos ticket has been acquired
|
||||||
5. Specify the test service host location `export ServiceHost=${ServiceHost}`. <br/>
|
5. Run tests as needed, such as with `${GitWcfRoot}/build.sh /p:WithCategories=OuterLoop /p:ServiceUri=${ServiceUri} /p:Negotiate_Available=true /p:Kerberos_Available=true`
|
||||||
_Note: this step is not needed if running tests using 'build.sh'_
|
See section titled "Test Conditions" to see what conditions are specifiable.
|
||||||
6. Initialize Kerberos by running `kinit ${NegotiateTestUserName}@${NegotiateTestRealm}`; enter the password for the user, ${NegotiateTestPassword}
|
6. Once tests are completed, run `kdestroy -A` on your Linux box
|
||||||
7. Run `klist` to see that the Kerberos ticket has been acquired
|
|
||||||
8. Run tests as needed, such as with `${GitWcfRoot}/build.sh /p:WithCategories=OuterLoop /p:BridgeHost=${BridgeHost}`
|
|
||||||
9. Once tests are completed, run `kdestroy -A` on your Linux box
|
|
||||||
10. Shut down the bridge by running `${GitWcfRoot}\stopBridge.cmd`
|
|
||||||
|
|
||||||
|
## Test conditions
|
||||||
|
Tests that require special conditions to run are Conditioned to prevent running when the conditions are not true - for example, a Kerberos environment may not be available on all machines, so these tests will not run by default. In order to run tests, we must specify each condition we know to be true on the command line - such as
|
||||||
|
|
||||||
|
`build.sh /p:WithCategories=OuterLoop /p:ServiceUri=${ServiceUri} /p:Negotiate_Available=true /p:Kerberos_Available=true`
|
||||||
|
|
||||||
|
Available conditions are:
|
||||||
|
|
||||||
|
* SPN_Available
|
||||||
|
* Ambient_Credentials_Available
|
||||||
|
* Explicit_Credentials_Available
|
||||||
|
* Basic_Authentication_Available
|
||||||
|
* Digest_Authentication_Available
|
||||||
|
* Windows_Authentication_Available
|
||||||
|
* NTLM_Available
|
||||||
|
* SSL_Available
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче