diff --git a/cmd/keymasterd/roleRequestingCert.go b/cmd/keymasterd/roleRequestingCert.go index e0c26ac..f420561 100644 --- a/cmd/keymasterd/roleRequestingCert.go +++ b/cmd/keymasterd/roleRequestingCert.go @@ -28,7 +28,7 @@ type roleRequestingCertGenParams struct { } func (state *RuntimeState) parseRoleCertGenParams(r *http.Request) (*roleRequestingCertGenParams, error, error) { - state.logger.Debugf(3, "Got client POST connection") + state.logger.Debugf(3, "parseRoleCertGenParams: Got client POST connection") err := r.ParseForm() if err != nil { state.logger.Println(err) @@ -154,7 +154,7 @@ func (state *RuntimeState) roleRequetingCertGenHandler(w http.ResponseWriter, r // TODO: this should be a different check, for now keep it to admin users if !state.isAutomationAdmin(authData.Username) { - state.writeFailureResponse(w, r, http.StatusUnauthorized, + state.writeFailureResponse(w, r, http.StatusForbidden, "Not an admin user") return } @@ -302,16 +302,9 @@ func (state *RuntimeState) parseRefreshRoleCertGenParams(authData *authInfo, r * func (state *RuntimeState) refreshRoleRequetingCertGenHandler(w http.ResponseWriter, r *http.Request) { var signerIsNull bool - //var keySigner crypto.Signer - // copy runtime singer if not nil state.Mutex.Lock() signerIsNull = (state.Signer == nil) - /* - if !signerIsNull { - keySigner = state.Signer - } - */ state.Mutex.Unlock() //local sanity tests diff --git a/cmd/keymasterd/roleRequestingCert_test.go b/cmd/keymasterd/roleRequestingCert_test.go index fd35066..3b4a4f6 100644 --- a/cmd/keymasterd/roleRequestingCert_test.go +++ b/cmd/keymasterd/roleRequestingCert_test.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "net" "net/http" + "net/http/httptest" "net/url" "os" "strconv" @@ -108,6 +109,90 @@ func TestRoleRequetingCertGenHandler(t *testing.T) { // TODO: check body content is actually pem } +func TestRoleRequetingCertGenHandlerTLSAuth(t *testing.T) { + state, tmpdir, err := testCreateRuntimeStateWithBothCAs(t) + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + state.Config.Base.AutomationUsers = append(state.Config.Base.AutomationUsers, "role1") + state.Config.Base.AutomationAdmins = append(state.Config.Base.AutomationAdmins, "admin1") + state.Config.Base.AllowedAuthBackendsForCerts = append(state.Config.Base.AllowedAuthBackendsForCerts, proto.AuthTypeIPCertificate) + + //Bob id not admin, should fail with forbidden + req := httptest.NewRequest("POST", getRoleRequestingPath, nil) + req.TLS, err = testMakeConnectionState("testdata/bob.pem", + "testdata/KeymasterCA.pem") + + _, err = checkRequestHandlerCode(req, state.roleRequetingCertGenHandler, http.StatusForbidden) + if err != nil { + t.Fatal(err) + } + + //alice is admin... but there is no data, it should fail + req = httptest.NewRequest("POST", getRoleRequestingPath, nil) + req.TLS, err = testMakeConnectionState("testdata/alice.pem", + "testdata/KeymasterCA.pem") + _, err = checkRequestHandlerCode(req, state.roleRequetingCertGenHandler, http.StatusBadRequest) + if err != nil { + t.Fatal(err) + } + // lets create valid inputs + userPemBlock, _ := pem.Decode([]byte(testUserPEMPublicKey)) + b64public := base64.RawURLEncoding.EncodeToString(userPemBlock.Bytes) + form := url.Values{} + form.Add("identity", "role1") + form.Add("requestor_netblock", "127.0.0.1/32") + form.Add("pubkey", b64public) + form.Add("target_netblock", "192.168.0.174/32") + + req2, err := http.NewRequest("POST", getRoleRequestingPath, strings.NewReader(form.Encode())) + if err != nil { + t.Fatal(err) + } + req2.Header.Add("Content-Length", strconv.Itoa(len(form.Encode()))) + req2.Header.Add("Content-Type", "application/x-www-form-urlencoded") + req2.TLS, err = testMakeConnectionState("testdata/alice.pem", + "testdata/KeymasterCA.pem") + rr, err := checkRequestHandlerCode(req2, state.roleRequetingCertGenHandler, http.StatusOK) + if err != nil { + t.Fatal(err) + } + // TODO: check body response is actual cert to get a cert + resp := rr.Result() + pemData, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + block, _ := pem.Decode(pemData) + if block.Type != "CERTIFICATE" { + t.Fatalf("no CERTIFICATE found") + } + rrCert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + t.Fatal(err) + } + req3, err := createKeyBodyRequest("POST", "/certgen/role1?type=x509", testUserPEMPublicKey, "") + if err != nil { + t.Fatal(err) + } + req3.RemoteAddr = "127.0.0.1:12345" + var fakePeerCertificates []*x509.Certificate + var fakeVerifiedChains [][]*x509.Certificate + fakePeerCertificates = append(fakePeerCertificates, rrCert) + fakeVerifiedChains = append(fakeVerifiedChains, fakePeerCertificates) + connectionState := &tls.ConnectionState{ + VerifiedChains: fakeVerifiedChains, + PeerCertificates: fakePeerCertificates} + req3.TLS = connectionState + _, err = checkRequestHandlerCode(req3, state.certGenHandler, http.StatusOK) + if err != nil { + t.Fatal(err) + } + // and now use the cert to +} + func TestRefreshRoleRequetingCertGenHandler(t *testing.T) { state, passwdFile, err := setupValidRuntimeStateSigner(t) if err != nil {