Lorenz Brun | aa6b734 | 2019-12-12 02:55:02 +0100 | [diff] [blame] | 1 | // Copyright 2020 The Monogon Project Authors. |
| 2 | // |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | // |
| 5 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | // you may not use this file except in compliance with the License. |
| 7 | // You may obtain a copy of the License at |
| 8 | // |
| 9 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | // |
| 11 | // Unless required by applicable law or agreed to in writing, software |
| 12 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | // See the License for the specific language governing permissions and |
| 15 | // limitations under the License. |
| 16 | |
| 17 | package integrity |
| 18 | |
| 19 | import ( |
| 20 | "bytes" |
| 21 | "crypto/tls" |
| 22 | "crypto/x509" |
| 23 | "errors" |
| 24 | "fmt" |
| 25 | "net" |
| 26 | "strings" |
| 27 | |
Lorenz Brun | aa6b734 | 2019-12-12 02:55:02 +0100 | [diff] [blame] | 28 | "google.golang.org/grpc" |
| 29 | "google.golang.org/grpc/credentials" |
Hendrik Hofstadt | 8efe51e | 2020-02-28 12:53:41 +0100 | [diff] [blame] | 30 | |
| 31 | "git.monogon.dev/source/nexantic.git/core/generated/api" |
| 32 | "git.monogon.dev/source/nexantic.git/core/internal/common" |
Lorenz Brun | aa6b734 | 2019-12-12 02:55:02 +0100 | [diff] [blame] | 33 | ) |
| 34 | |
| 35 | // Agent specifices the interface which every integrity agent needs to fulfill |
Leopold Schabel | 8fba0f8 | 2020-01-22 18:46:25 +0100 | [diff] [blame] | 36 | // TODO: This interface is not yet used, we call the TPM2 agent directly. |
Lorenz Brun | aa6b734 | 2019-12-12 02:55:02 +0100 | [diff] [blame] | 37 | type Agent interface { |
| 38 | // Initialize needs to be called once and initializes the systems required to maintain integrity |
| 39 | // on the given platform. |
| 40 | // nodeCert is a X.509 DER certificate which identifies the node once it's unlocked. This is |
| 41 | // required to bind the node certificate (which is only available when the node is unlocked) to |
| 42 | // the integrity subsystem used to attest said node. |
| 43 | // Initialize returns the cryptographic identity that it's bound to. |
| 44 | Initialize(newNode api.NewNodeInfo, enrolment api.EnrolmentConfig) (string, error) |
| 45 | |
Leopold Schabel | 8fba0f8 | 2020-01-22 18:46:25 +0100 | [diff] [blame] | 46 | // Unlock performs all required actions to assure the integrity of the platform and securely retrieves |
| 47 | // the unlock key. |
Lorenz Brun | aa6b734 | 2019-12-12 02:55:02 +0100 | [diff] [blame] | 48 | Unlock(enrolment api.EnrolmentConfig) ([]byte, error) |
| 49 | } |
| 50 | |
| 51 | // DialNMS creates a secure GRPC connection to the NodeManagementService |
| 52 | func DialNMS(enrolment api.EnrolmentConfig) (*grpc.ClientConn, error) { |
| 53 | var targets []string |
| 54 | for _, target := range enrolment.MasterIps { |
| 55 | targets = append(targets, fmt.Sprintf("%v:%v", net.IP(target), common.MasterServicePort)) |
| 56 | } |
| 57 | cert, err := x509.ParseCertificate(enrolment.MastersCert) |
| 58 | if err != nil { |
| 59 | return nil, err |
| 60 | } |
| 61 | mastersPool := x509.NewCertPool() |
| 62 | mastersPool.AddCert(cert) |
| 63 | |
| 64 | secureTransport := &tls.Config{ |
| 65 | InsecureSkipVerify: true, |
| 66 | // Critical function, please review any changes with care |
| 67 | // TODO(lorenz): Actively check that this actually provides the security guarantees that we need |
| 68 | VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { |
| 69 | for _, cert := range rawCerts { |
| 70 | // X.509 certificates in DER can be compared like this since DER has a unique representation |
| 71 | // for each certificate. |
| 72 | if bytes.Equal(cert, enrolment.MastersCert) { |
| 73 | return nil |
| 74 | } |
| 75 | } |
| 76 | return errors.New("failed to find authorized NMS certificate") |
| 77 | }, |
| 78 | MinVersion: tls.VersionTLS13, |
| 79 | } |
| 80 | secureTransportCreds := credentials.NewTLS(secureTransport) |
| 81 | |
| 82 | return grpc.Dial(strings.Join(targets, ","), grpc.WithTransportCredentials(secureTransportCreds)) |
| 83 | } |