zrhoffman opened a new pull request, #7392:
URL: https://github.com/apache/trafficcontrol/pull/7392

   <!--
   Thank you for contributing! Please be sure to read our contribution 
guidelines: https://github.com/apache/trafficcontrol/blob/master/CONTRIBUTING.md
   If this closes or relates to an existing issue, please reference it using 
one of the following:
   
   Closes: #ISSUE
   Related: #ISSUE
   
   If this PR fixes a security vulnerability, DO NOT submit! Instead, contact
   the Apache Traffic Control Security Team at 
[email protected] and follow the
   guidelines at https://apache.org/security regarding vulnerability disclosure.
   -->
   
   ## Overview
   
   (Largely reposting @tcfdev's PR description from #7110):
   
   This PR implements #6622 by adding the ability for a Traffic Ops instance to 
accept TLS certificates from a client request and verify them against specified 
Root CA's certificate as a form of login. This is not to be confused with mTLS, 
albeit has a similar design. Should a client _not_ send a TLS certificate as 
part of the request login functionality will default to standard form 
authentication (current implementation).
   
   ## Client
   
   The client will provide a TLS certificate (and intermediate(s)) when hitting 
the `/user/login` endpoint.
   
   The client will need to attach a certificate (and intermediate(s)) that was 
provided by the Root CA. The client certificate will need to contain a UID 
Relative Distinguished Name in the DN for the x509 certificate. The object 
identifier for this field is:
   
   `0.9.2342.19200300.100.1.1`
   
   This will result in a subject that looks something like:
   
   ```
   Subject: C=US, ST=Colorado, L=Denver, O=Apache, OU=ATC, 
CN=client.local/UID=userid
   ```
   
   ## Traffic Ops
   
   In `cnd.conf` there is a new section to define the location of the Root CA 
certificates that are used for verification.
   
   _*cdn.conf*_
   ```json
   "client_certificate_authentication" : {
       "root_certificates_directory" : "/etc/pki/tls/certs/"
   }
   ```
   
   Additionally, to enable a line must be added to the 
`traffic_ops_golang.tls_config` section if it exists. If this section is not 
present, ClientAuth will be enabled (but not required) by default.
   
   _*cdn.conf*_
   ````jsonc
   "traffic_ops_golang" : {
   // ... other configuration values
       "tls_config": {
           "MinVersion": 769,
           "ClientAuth" : 1 // <---- Enables requesting the client certificate
       }
   }
   ````
   
   Traffic Ops does not require the client TLS certificate to be present. And 
will not verify the client provided TLS certificates during the TLS handshake 
when establishing a connection. Only if the client sends a TLS certificate to 
the `/user/login` will it be processed. If the certificate (and 
intermediate(s)) provided by the client verifies correctly against the defined 
Root certificates, the UID field will be parsed. If there is more than 1 UID 
field, only the first one is accepted. Order is not guaranteed. The UID value 
will then be used for authentication.
   
   Should the TLS certificate authentication fail at any point, Traffic Ops 
will attempt to perform form value authentication (username and password) which 
is the current functionality. TLS client certificate authentication is not 
present on Oauth or Token login endpoints currently.
   
   <!-- **^ Add meaningful description above** --><hr/>
   
   ## Which Traffic Control components are affected by this PR?
   <!-- Please delete all components from this list that are NOT affected by 
this PR.
   Feel free to add the name of a tool or script that is affected but not on 
the list.
   -->
   - Documentation
   - Traffic Ops
   
   ## What is the best way to verify this PR?
   <!-- Please include here ALL the steps necessary to test your PR.
   If your PR has tests (and most should), provide the steps needed to run the 
tests.
   If not, please provide step-by-step instructions to test the PR manually and 
explain why your PR does not need tests. -->
   
   ## Unit
   
   Verify unit tests pass. Unit tests have been added to test TLS 
authentication. Existing unit tests ensure current default behavior continues 
to work as expected.
   
   ## Manual
   
   Test certificates can be created using the file located at 
`trafficcontrol/experimental/certificate_auth/generate_certs.go`. Running `go 
run generate_certs.go` will produce private keys and certificates for Root, 
Intermediate, and Client (Server cert/key is also created, but can be ignored 
since they too are used only in tests). Place the Root certificate in the 
directory location specified in the `cdn.conf` file.
   
   Launch a Traffic Ops instance.
   
   Ensure a user exists with appropriate permissions with the name `userid` 
(This can be changed in the `generate_certs.go` file if you want to use a 
different username).
   
   Send a request to the `user/login` Traffic Ops with the Client and 
Intermediate certs. For a Go client this would look something like:
   
   _client.go_ A more complete version can be found at 
`trafficcontrol/experimental/certificate_auth/example/client.go`
   ```go
   func main() {
        // LoadX509KeyPair can also load certificate chain with intermediates
        cert, _ := 
tls.LoadX509KeyPair("../certs/client-intermediate-chain.crt.pem", 
"../certs/client.key.pem")
   
        transport := &http.Transport{
                TLSClientConfig: &tls.Config{
                        Certificates: []tls.Certificate{cert},
                },
        }
   
        client := http.Client{
                Timeout:   time.Second * 60,
                Transport: transport,
        }
   
        req, _ := http.NewRequest(
                http.MethodPost,
                "https://server.local:8443/api/4.0/user/login";,
                bytes.NewBufferString(""),
        )
   
        resp, _ := client.Do(req)
        defer resp.Body.Close()
   
        respBody, _ := ioutil.ReadAll(resp.Body)
   
        fmt.Println(string(respBody)) // Verify Success
        fmt.Println(resp.Cookies()) // Verify Cookie(s)
   }
   ```
   
   Upon success, a 200 OK status code will be returned along with the following 
body:
   ```json
   {
       "alerts": [
           {
               "text": "Successfully logged in.",
               "level": "success"
           }
       ]
   }
   ```
   
   Additional tests may also be performed if desired, such as sending a POST 
request with a username/password body and no certificate (current behavior). Or 
a bad cert (either malformed or not signed by the correct Root CA) with or 
without username/password form.
   
   
   ## PR submission checklist
   - [x] This PR has tests <!-- If not, please delete this text and explain why 
this PR does not need tests. -->
   - [x] This PR has documentation <!-- If not, please delete this text and 
explain why this PR does not need documentation. -->
   - [x] This PR has a CHANGELOG.md entry <!-- A fix for a bug from an ATC 
release, an improvement, or a new feature should have a changelog entry. -->
   - [x] This PR **DOES NOT FIX A SERIOUS SECURITY VULNERABILITY** (see [the 
Apache Software Foundation's security guidelines](https://apache.org/security) 
for details)
   
   <!--
   Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
   distributed with this work for additional information
   regarding copyright ownership.  The ASF licenses this file
   to you 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.
   -->


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to