blob: 67fcd83e3ee47daba482184ef8b01e3c49a7330d [file] [log] [blame]
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +02001// 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
17package api
18
19import (
20 "context"
21 "crypto/rand"
Lorenz Brun878f5f92020-05-12 16:15:39 +020022 "encoding/hex"
Lorenz Brunaa6b7342019-12-12 02:55:02 +010023 "io"
24
Lorenz Brunaa6b7342019-12-12 02:55:02 +010025 "github.com/gogo/protobuf/proto"
26 "go.etcd.io/etcd/clientv3"
Serge Bazanski7ba31522020-02-03 16:08:19 +010027 "google.golang.org/grpc/codes"
28 "google.golang.org/grpc/status"
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +020029
Hendrik Hofstadt8efe51e2020-02-28 12:53:41 +010030 "git.monogon.dev/source/nexantic.git/core/generated/api"
31 schema "git.monogon.dev/source/nexantic.git/core/generated/api"
32
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +020033 "go.uber.org/zap"
34)
35
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +020036func (s *Server) AddNode(ctx context.Context, req *schema.AddNodeRequest) (*schema.AddNodeResponse, error) {
Lorenz Brunaa6b7342019-12-12 02:55:02 +010037 return nil, status.Error(codes.Unimplemented, "Unimplemented")
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +020038}
39
Lorenz Brunaa6b7342019-12-12 02:55:02 +010040func (s *Server) RemoveNode(ctx context.Context, req *schema.RemoveNodeRequest) (*schema.RemoveNodeRequest, error) {
41 return nil, status.Error(codes.Unimplemented, "Unimplemented")
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +020042}
43
Lorenz Brunaa6b7342019-12-12 02:55:02 +010044func (s *Server) ListNodes(ctx context.Context, req *schema.ListNodesRequest) (*schema.ListNodesResponse, error) {
45 store := s.getStore()
46 res, err := store.Get(ctx, "nodes/", clientv3.WithPrefix())
47 if err != nil {
48 return nil, status.Error(codes.Unavailable, "Consensus unavailable")
49 }
50 var resNodes []*api.Node
51 for _, nodeEntry := range res.Kvs {
52 var node api.Node
53 if err := proto.Unmarshal(nodeEntry.Value, &node); err != nil {
54 s.Logger.Error("Encountered invalid node data", zap.Error(err))
55 return nil, status.Error(codes.Internal, "Invalid data")
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +020056 }
Lorenz Brunaa6b7342019-12-12 02:55:02 +010057 // Zero out Global Unlock Key, it's never supposed to leave the cluster
58 node.GlobalUnlockKey = []byte{}
59
60 resNodes = append(resNodes, &node)
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +020061 }
62
Leopold Schabel68c58752019-11-14 21:00:59 +010063 return &schema.ListNodesResponse{
Hendrik Hofstadt0d7c91e2019-10-23 21:44:47 +020064 Nodes: resNodes,
65 }, nil
66}
Lorenz Brunaa6b7342019-12-12 02:55:02 +010067
68func (s *Server) ListEnrolmentConfigs(ctx context.Context, req *api.ListEnrolmentConfigsRequest) (*api.ListEnrolmentConfigsResponse, error) {
69 return nil, status.Error(codes.Unimplemented, "Unimplemented")
70}
71
72func (s *Server) NewEnrolmentConfig(ctx context.Context, req *api.NewEnrolmentConfigRequest) (*api.NewEnrolmentConfigResponse, error) {
73 store := s.getStore()
74 token := make([]byte, 32)
75 if _, err := io.ReadFull(rand.Reader, token); err != nil {
76 return nil, status.Error(codes.Unavailable, "failed to get randonmess")
77 }
78 nodes, err := store.Get(ctx, "nodes/", clientv3.WithPrefix())
79 if err != nil {
80 return nil, status.Error(codes.Unavailable, "consensus unavailable")
81 }
82 var masterIPs [][]byte
83 for _, nodeKV := range nodes.Kvs {
84 var node api.Node
85 if err := proto.Unmarshal(nodeKV.Value, &node); err != nil {
86 return nil, status.Error(codes.Internal, "invalid node")
87 }
88 if node.State == api.Node_MASTER {
89 masterIPs = append(masterIPs, node.Address)
90 }
91 }
92 masterCert, err := s.GetMasterCert()
93 if err != nil {
94 return nil, status.Error(codes.Unavailable, "consensus unavailable")
95 }
96
97 enrolmentConfig := &api.EnrolmentConfig{
98 EnrolmentSecret: token,
99 MasterIps: masterIPs,
100 MastersCert: masterCert,
101 }
102 enrolmentConfigRaw, err := proto.Marshal(enrolmentConfig)
103 if err != nil {
104 return nil, status.Error(codes.Internal, "failed to encode config")
105 }
Lorenz Brun878f5f92020-05-12 16:15:39 +0200106 if _, err := store.Put(ctx, "enrolments/"+hex.EncodeToString(token), string(enrolmentConfigRaw)); err != nil {
Lorenz Brunaa6b7342019-12-12 02:55:02 +0100107 return nil, status.Error(codes.Unavailable, "consensus unavailable")
108 }
109 return &schema.NewEnrolmentConfigResponse{
110 EnrolmentConfig: enrolmentConfig,
111 }, nil
112}
113
114func (s *Server) RemoveEnrolmentConfig(ctx context.Context, req *api.RemoveEnrolmentConfigRequest) (*api.RemoveEnrolmentConfigResponse, error) {
115 return nil, status.Error(codes.Unimplemented, "Unimplemented")
116}