mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-02-23 16:30:11 -05:00
AB#2046 : Add option to create SSH users for the first coordinator upon initialization (#133)
* Move `file`, `ssh` and `user` packages to internal * Rename `SSHKey` to `(ssh.)UserKey` * Rename KeyValue / Publickey to PublicKey * Rename SSH key file from "debugd" to "ssh-keys" * Add CreateSSHUsers function to Core * Call CreateSSHUsers users on first control-plane node, when defined in config Tests: * Make StubUserCreator add entries to /etc/passwd * Add NewLinuxUserManagerFake for unit tests * Add unit tests & adjust existing ones to changes
This commit is contained in:
parent
5dc2e71d80
commit
68092f27dd
@ -1,9 +1,9 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/internal/config"
|
"github.com/edgelesssys/constellation/internal/config"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
@ -4,9 +4,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/internal/config"
|
"github.com/edgelesssys/constellation/internal/config"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -8,10 +8,10 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/cli/azure"
|
"github.com/edgelesssys/constellation/cli/azure"
|
||||||
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
||||||
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/cli/gcp"
|
"github.com/edgelesssys/constellation/cli/gcp"
|
||||||
"github.com/edgelesssys/constellation/internal/config"
|
"github.com/edgelesssys/constellation/internal/config"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -9,9 +9,9 @@ import (
|
|||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/azure"
|
"github.com/edgelesssys/constellation/cli/azure"
|
||||||
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/cli/gcp"
|
"github.com/edgelesssys/constellation/cli/gcp"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/edgelesssys/constellation/internal/state"
|
"github.com/edgelesssys/constellation/internal/state"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -14,16 +14,18 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/cli/azure"
|
"github.com/edgelesssys/constellation/cli/azure"
|
||||||
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
||||||
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/cli/gcp"
|
"github.com/edgelesssys/constellation/cli/gcp"
|
||||||
"github.com/edgelesssys/constellation/cli/proto"
|
"github.com/edgelesssys/constellation/cli/proto"
|
||||||
"github.com/edgelesssys/constellation/cli/status"
|
"github.com/edgelesssys/constellation/cli/status"
|
||||||
"github.com/edgelesssys/constellation/cli/vpn"
|
"github.com/edgelesssys/constellation/cli/vpn"
|
||||||
"github.com/edgelesssys/constellation/coordinator/atls"
|
"github.com/edgelesssys/constellation/coordinator/atls"
|
||||||
|
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
|
||||||
coordinatorstate "github.com/edgelesssys/constellation/coordinator/state"
|
coordinatorstate "github.com/edgelesssys/constellation/coordinator/state"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util"
|
"github.com/edgelesssys/constellation/coordinator/util"
|
||||||
"github.com/edgelesssys/constellation/internal/config"
|
"github.com/edgelesssys/constellation/internal/config"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/edgelesssys/constellation/internal/state"
|
"github.com/edgelesssys/constellation/internal/state"
|
||||||
"github.com/kr/text"
|
"github.com/kr/text"
|
||||||
wgquick "github.com/nmiculinic/wg-quick-go"
|
wgquick "github.com/nmiculinic/wg-quick-go"
|
||||||
@ -78,6 +80,8 @@ func initialize(ctx context.Context, cmd *cobra.Command, protCl protoClient, ser
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protoSSHUserKeys := ssh.ToProtoSlice(config.SSHUsers)
|
||||||
|
|
||||||
var stat state.ConstellationState
|
var stat state.ConstellationState
|
||||||
err = fileHandler.ReadJSON(constants.StateFilename, &stat)
|
err = fileHandler.ReadJSON(constants.StateFilename, &stat)
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
@ -129,6 +133,7 @@ func initialize(ctx context.Context, cmd *cobra.Command, protCl protoClient, ser
|
|||||||
coordinatorPrivIPs: coordinators.PrivateIPs()[1:],
|
coordinatorPrivIPs: coordinators.PrivateIPs()[1:],
|
||||||
autoscalingNodeGroups: autoscalingNodeGroups,
|
autoscalingNodeGroups: autoscalingNodeGroups,
|
||||||
cloudServiceAccountURI: serviceAccount,
|
cloudServiceAccountURI: serviceAccount,
|
||||||
|
sshUserKeys: protoSSHUserKeys,
|
||||||
}
|
}
|
||||||
result, err := activate(ctx, cmd, protCl, input, validators.V())
|
result, err := activate(ctx, cmd, protCl, input, validators.V())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -166,7 +171,7 @@ func activate(ctx context.Context, cmd *cobra.Command, client protoClient, input
|
|||||||
return activationResult{}, err
|
return activationResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
respCl, err := client.Activate(ctx, input.pubKey, input.masterSecret, input.nodePrivIPs, input.coordinatorPrivIPs, input.autoscalingNodeGroups, input.cloudServiceAccountURI)
|
respCl, err := client.Activate(ctx, input.pubKey, input.masterSecret, input.nodePrivIPs, input.coordinatorPrivIPs, input.autoscalingNodeGroups, input.cloudServiceAccountURI, input.sshUserKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return activationResult{}, err
|
return activationResult{}, err
|
||||||
}
|
}
|
||||||
@ -216,6 +221,7 @@ type activationInput struct {
|
|||||||
coordinatorPrivIPs []string
|
coordinatorPrivIPs []string
|
||||||
autoscalingNodeGroups []string
|
autoscalingNodeGroups []string
|
||||||
cloudServiceAccountURI string
|
cloudServiceAccountURI string
|
||||||
|
sshUserKeys []*pubproto.SSHUserKey
|
||||||
}
|
}
|
||||||
|
|
||||||
type activationResult struct {
|
type activationResult struct {
|
||||||
|
@ -12,10 +12,10 @@ import (
|
|||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/azure"
|
"github.com/edgelesssys/constellation/cli/azure"
|
||||||
"github.com/edgelesssys/constellation/cli/ec2"
|
"github.com/edgelesssys/constellation/cli/ec2"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/cli/gcp"
|
"github.com/edgelesssys/constellation/cli/gcp"
|
||||||
"github.com/edgelesssys/constellation/cli/qemu"
|
"github.com/edgelesssys/constellation/cli/qemu"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/edgelesssys/constellation/internal/state"
|
"github.com/edgelesssys/constellation/internal/state"
|
||||||
wgquick "github.com/nmiculinic/wg-quick-go"
|
wgquick "github.com/nmiculinic/wg-quick-go"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/proto"
|
"github.com/edgelesssys/constellation/cli/proto"
|
||||||
"github.com/edgelesssys/constellation/coordinator/atls"
|
"github.com/edgelesssys/constellation/coordinator/atls"
|
||||||
|
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
|
||||||
"github.com/edgelesssys/constellation/coordinator/state"
|
"github.com/edgelesssys/constellation/coordinator/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -12,5 +13,5 @@ type protoClient interface {
|
|||||||
Connect(endpoint string, validators []atls.Validator) error
|
Connect(endpoint string, validators []atls.Validator) error
|
||||||
Close() error
|
Close() error
|
||||||
GetState(ctx context.Context) (state.State, error)
|
GetState(ctx context.Context) (state.State, error)
|
||||||
Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs, autoscalingNodeGroups []string, cloudServiceAccountURI string) (proto.ActivationResponseClient, error)
|
Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs, autoscalingNodeGroups []string, cloudServiceAccountURI string, sshUsers []*pubproto.SSHUserKey) (proto.ActivationResponseClient, error)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/proto"
|
"github.com/edgelesssys/constellation/cli/proto"
|
||||||
"github.com/edgelesssys/constellation/coordinator/atls"
|
"github.com/edgelesssys/constellation/coordinator/atls"
|
||||||
|
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
|
||||||
"github.com/edgelesssys/constellation/coordinator/state"
|
"github.com/edgelesssys/constellation/coordinator/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ type stubProtoClient struct {
|
|||||||
activateCoordinatorIPs []string
|
activateCoordinatorIPs []string
|
||||||
activateAutoscalingNodeGroups []string
|
activateAutoscalingNodeGroups []string
|
||||||
cloudServiceAccountURI string
|
cloudServiceAccountURI string
|
||||||
|
sshUserKeys []*pubproto.SSHUserKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *stubProtoClient) Connect(_ string, _ []atls.Validator) error {
|
func (c *stubProtoClient) Connect(_ string, _ []atls.Validator) error {
|
||||||
@ -42,13 +44,14 @@ func (c *stubProtoClient) GetState(_ context.Context) (state.State, error) {
|
|||||||
return c.getStateState, c.getStateErr
|
return c.getStateState, c.getStateErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *stubProtoClient) Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs []string, autoscalingNodeGroups []string, cloudServiceAccountURI string) (proto.ActivationResponseClient, error) {
|
func (c *stubProtoClient) Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs []string, autoscalingNodeGroups []string, cloudServiceAccountURI string, sshUserKeys []*pubproto.SSHUserKey) (proto.ActivationResponseClient, error) {
|
||||||
c.activateUserPublicKey = userPublicKey
|
c.activateUserPublicKey = userPublicKey
|
||||||
c.activateMasterSecret = masterSecret
|
c.activateMasterSecret = masterSecret
|
||||||
c.activateNodeIPs = nodeIPs
|
c.activateNodeIPs = nodeIPs
|
||||||
c.activateCoordinatorIPs = coordinatorIPs
|
c.activateCoordinatorIPs = coordinatorIPs
|
||||||
c.activateAutoscalingNodeGroups = autoscalingNodeGroups
|
c.activateAutoscalingNodeGroups = autoscalingNodeGroups
|
||||||
c.cloudServiceAccountURI = cloudServiceAccountURI
|
c.cloudServiceAccountURI = cloudServiceAccountURI
|
||||||
|
c.sshUserKeys = sshUserKeys
|
||||||
|
|
||||||
return c.respClient, c.activateErr
|
return c.respClient, c.activateErr
|
||||||
}
|
}
|
||||||
@ -126,7 +129,7 @@ func (c *fakeProtoClient) GetState(_ context.Context) (state.State, error) {
|
|||||||
return state.IsNode, nil
|
return state.IsNode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeProtoClient) Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs, autoscalingNodeGroups []string, cloudServiceAccountURI string) (proto.ActivationResponseClient, error) {
|
func (c *fakeProtoClient) Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs, autoscalingNodeGroups []string, cloudServiceAccountURI string, sshUserKeys []*pubproto.SSHUserKey) (proto.ActivationResponseClient, error) {
|
||||||
if !c.conn {
|
if !c.conn {
|
||||||
return nil, errors.New("client is not connected")
|
return nil, errors.New("client is not connected")
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,11 @@ import (
|
|||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
||||||
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/cli/proto"
|
"github.com/edgelesssys/constellation/cli/proto"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util"
|
"github.com/edgelesssys/constellation/coordinator/util"
|
||||||
"github.com/edgelesssys/constellation/internal/config"
|
"github.com/edgelesssys/constellation/internal/config"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/edgelesssys/constellation/internal/state"
|
"github.com/edgelesssys/constellation/internal/state"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -6,8 +6,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/edgelesssys/constellation/internal/state"
|
"github.com/edgelesssys/constellation/internal/state"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -10,8 +10,8 @@ import (
|
|||||||
"go.uber.org/multierr"
|
"go.uber.org/multierr"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/edgelesssys/constellation/internal/state"
|
"github.com/edgelesssys/constellation/internal/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/edgelesssys/constellation/internal/state"
|
"github.com/edgelesssys/constellation/internal/state"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -7,10 +7,10 @@ import (
|
|||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
"github.com/edgelesssys/constellation/cli/cloud/cloudcmd"
|
||||||
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/cli/proto"
|
"github.com/edgelesssys/constellation/cli/proto"
|
||||||
"github.com/edgelesssys/constellation/internal/config"
|
"github.com/edgelesssys/constellation/internal/config"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
rpcStatus "google.golang.org/grpc/status"
|
rpcStatus "google.golang.org/grpc/status"
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
"github.com/edgelesssys/constellation/cli/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -73,7 +73,7 @@ func (c *Client) GetState(ctx context.Context) (state.State, error) {
|
|||||||
// Activate activates the Constellation coordinator via a grpc call.
|
// Activate activates the Constellation coordinator via a grpc call.
|
||||||
// The handed IP addresses must be the private IP addresses of running AWS or GCP instances,
|
// The handed IP addresses must be the private IP addresses of running AWS or GCP instances,
|
||||||
// and the userPublicKey is the VPN key of the users WireGuard interface.
|
// and the userPublicKey is the VPN key of the users WireGuard interface.
|
||||||
func (c *Client) Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs, autoscalingNodeGroups []string, cloudServiceAccountURI string) (ActivationResponseClient, error) {
|
func (c *Client) Activate(ctx context.Context, userPublicKey, masterSecret []byte, nodeIPs, coordinatorIPs, autoscalingNodeGroups []string, cloudServiceAccountURI string, sshUserKeys []*pubproto.SSHUserKey) (ActivationResponseClient, error) {
|
||||||
if c.pubapi == nil {
|
if c.pubapi == nil {
|
||||||
return nil, errors.New("client is not connected")
|
return nil, errors.New("client is not connected")
|
||||||
}
|
}
|
||||||
@ -100,6 +100,7 @@ func (c *Client) Activate(ctx context.Context, userPublicKey, masterSecret []byt
|
|||||||
KeyEncryptionKeyId: "",
|
KeyEncryptionKeyId: "",
|
||||||
UseExistingKek: false,
|
UseExistingKek: false,
|
||||||
CloudServiceAccountUri: cloudServiceAccountURI,
|
CloudServiceAccountUri: cloudServiceAccountURI,
|
||||||
|
SshUserKeys: sshUserKeys,
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := c.pubapi.ActivateAsCoordinator(ctx, req)
|
client, err := c.pubapi.ActivateAsCoordinator(ctx, req)
|
||||||
|
@ -163,7 +163,7 @@ func TestActivate(t *testing.T) {
|
|||||||
if tc.pubAPIClient != nil {
|
if tc.pubAPIClient != nil {
|
||||||
client.pubapi = tc.pubAPIClient
|
client.pubapi = tc.pubAPIClient
|
||||||
}
|
}
|
||||||
_, err := client.Activate(context.Background(), []byte(tc.userPublicKey), []byte("Constellation"), tc.ips, nil, nil, "serviceaccount://test")
|
_, err := client.Activate(context.Background(), []byte(tc.userPublicKey), []byte("Constellation"), tc.ips, nil, nil, "serviceaccount://test", nil)
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/azure"
|
"github.com/edgelesssys/constellation/coordinator/attestation/azure"
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/gcp"
|
"github.com/edgelesssys/constellation/coordinator/attestation/gcp"
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/qemu"
|
"github.com/edgelesssys/constellation/coordinator/attestation/qemu"
|
||||||
@ -27,6 +26,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/util"
|
"github.com/edgelesssys/constellation/coordinator/util"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
||||||
"github.com/edgelesssys/constellation/coordinator/wireguard"
|
"github.com/edgelesssys/constellation/coordinator/wireguard"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
|
grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@ -174,5 +174,5 @@ func main() {
|
|||||||
netDialer := &net.Dialer{}
|
netDialer := &net.Dialer{}
|
||||||
dialer := grpcutil.NewDialer(validator, netDialer)
|
dialer := grpcutil.NewDialer(validator, netDialer)
|
||||||
run(issuer, wg, openTPM, util.GetIPAddr, dialer, fileHandler, kube,
|
run(issuer, wg, openTPM, util.GetIPAddr, dialer, fileHandler, kube,
|
||||||
metadata, cloudControllerManager, cloudNodeManager, autoscaler, encryptedDisk, etcdEndpoint, enforceEtcdTls, bindIP, bindPort, zapLoggerCore)
|
metadata, cloudControllerManager, cloudNodeManager, autoscaler, encryptedDisk, etcdEndpoint, enforceEtcdTls, bindIP, bindPort, zapLoggerCore, fs)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/atls"
|
"github.com/edgelesssys/constellation/coordinator/atls"
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
||||||
"github.com/edgelesssys/constellation/coordinator/core"
|
"github.com/edgelesssys/constellation/coordinator/core"
|
||||||
@ -17,9 +16,12 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
||||||
"github.com/edgelesssys/constellation/coordinator/vpnapi"
|
"github.com/edgelesssys/constellation/coordinator/vpnapi"
|
||||||
"github.com/edgelesssys/constellation/coordinator/vpnapi/vpnproto"
|
"github.com/edgelesssys/constellation/coordinator/vpnapi/vpnproto"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||||
grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
|
grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
|
||||||
grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
|
grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
|
||||||
|
"github.com/spf13/afero"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
@ -29,6 +31,7 @@ var version = "0.0.0"
|
|||||||
|
|
||||||
func run(issuer core.QuoteIssuer, vpn core.VPN, openTPM vtpm.TPMOpenFunc, getPublicIPAddr func() (string, error), dialer *grpcutil.Dialer, fileHandler file.Handler,
|
func run(issuer core.QuoteIssuer, vpn core.VPN, openTPM vtpm.TPMOpenFunc, getPublicIPAddr func() (string, error), dialer *grpcutil.Dialer, fileHandler file.Handler,
|
||||||
kube core.Cluster, metadata core.ProviderMetadata, cloudControllerManager core.CloudControllerManager, cloudNodeManager core.CloudNodeManager, clusterAutoscaler core.ClusterAutoscaler, encryptedDisk core.EncryptedDisk, etcdEndpoint string, etcdTLS bool, bindIP, bindPort string, zapLoggerCore *zap.Logger,
|
kube core.Cluster, metadata core.ProviderMetadata, cloudControllerManager core.CloudControllerManager, cloudNodeManager core.CloudNodeManager, clusterAutoscaler core.ClusterAutoscaler, encryptedDisk core.EncryptedDisk, etcdEndpoint string, etcdTLS bool, bindIP, bindPort string, zapLoggerCore *zap.Logger,
|
||||||
|
fs afero.Fs,
|
||||||
) {
|
) {
|
||||||
defer zapLoggerCore.Sync()
|
defer zapLoggerCore.Sync()
|
||||||
zapLoggerCore.Info("starting coordinator", zap.String("version", version))
|
zapLoggerCore.Info("starting coordinator", zap.String("version", version))
|
||||||
@ -43,7 +46,8 @@ func run(issuer core.QuoteIssuer, vpn core.VPN, openTPM vtpm.TPMOpenFunc, getPub
|
|||||||
ForceTLS: etcdTLS,
|
ForceTLS: etcdTLS,
|
||||||
Logger: zapLoggerCore.WithOptions(zap.IncreaseLevel(zap.WarnLevel)).Named("etcd"),
|
Logger: zapLoggerCore.WithOptions(zap.IncreaseLevel(zap.WarnLevel)).Named("etcd"),
|
||||||
}
|
}
|
||||||
core, err := core.NewCore(vpn, kube, metadata, cloudControllerManager, cloudNodeManager, clusterAutoscaler, encryptedDisk, zapLoggerCore, openTPM, etcdStoreFactory, fileHandler)
|
linuxUserManager := user.NewLinuxUserManager(fs)
|
||||||
|
core, err := core.NewCore(vpn, kube, metadata, cloudControllerManager, cloudNodeManager, clusterAutoscaler, encryptedDisk, zapLoggerCore, openTPM, etcdStoreFactory, fileHandler, linuxUserManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zapLoggerCore.Fatal("failed to create core", zap.Error(err))
|
zapLoggerCore.Fatal("failed to create core", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/atls"
|
"github.com/edgelesssys/constellation/coordinator/atls"
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
||||||
"github.com/edgelesssys/constellation/coordinator/core"
|
"github.com/edgelesssys/constellation/coordinator/core"
|
||||||
@ -21,6 +20,8 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
||||||
"github.com/edgelesssys/constellation/coordinator/vpnapi"
|
"github.com/edgelesssys/constellation/coordinator/vpnapi"
|
||||||
"github.com/edgelesssys/constellation/coordinator/vpnapi/vpnproto"
|
"github.com/edgelesssys/constellation/coordinator/vpnapi/vpnproto"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -211,7 +212,8 @@ func TestConcurrent(t *testing.T) {
|
|||||||
|
|
||||||
func spawnPeer(require *require.Assertions, logger *zap.Logger, netDialer *testdialer.BufconnDialer, netw *network, endpoint string) (*grpc.Server, *pubapi.API, *fakeVPN) {
|
func spawnPeer(require *require.Assertions, logger *zap.Logger, netDialer *testdialer.BufconnDialer, netw *network, endpoint string) (*grpc.Server, *pubapi.API, *fakeVPN) {
|
||||||
vpn := newVPN(netw, endpoint)
|
vpn := newVPN(netw, endpoint)
|
||||||
cor, err := core.NewCore(vpn, &core.ClusterFake{}, &core.ProviderMetadataFake{}, &core.CloudControllerManagerFake{}, &core.CloudNodeManagerFake{}, &core.ClusterAutoscalerFake{}, &core.EncryptedDiskFake{}, logger, simulator.OpenSimulatedTPM, fakeStoreFactory{}, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
cor, err := core.NewCore(vpn, &core.ClusterFake{}, &core.ProviderMetadataFake{}, &core.CloudControllerManagerFake{}, &core.CloudNodeManagerFake{}, &core.ClusterAutoscalerFake{}, &core.EncryptedDiskFake{}, logger, simulator.OpenSimulatedTPM, fakeStoreFactory{}, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
require.NoError(cor.AdvanceState(state.AcceptingInit, nil, nil))
|
require.NoError(cor.AdvanceState(state.AcceptingInit, nil, nil))
|
||||||
|
|
||||||
|
@ -6,11 +6,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
||||||
"github.com/edgelesssys/constellation/coordinator/kubernetes"
|
"github.com/edgelesssys/constellation/coordinator/kubernetes"
|
||||||
"github.com/edgelesssys/constellation/coordinator/kubernetes/k8sapi/resources"
|
"github.com/edgelesssys/constellation/coordinator/kubernetes/k8sapi/resources"
|
||||||
"github.com/edgelesssys/constellation/coordinator/role"
|
"github.com/edgelesssys/constellation/coordinator/role"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -171,7 +172,8 @@ func TestInitCluster(t *testing.T) {
|
|||||||
|
|
||||||
zapLogger, err := zap.NewDevelopment()
|
zapLogger, err := zap.NewDevelopment()
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
core, err := NewCore(&stubVPN{}, &tc.cluster, &tc.metadata, &tc.cloudControllerManager, &tc.cloudNodeManager, &tc.clusterAutoscaler, nil, zapLogger, simulator.OpenSimulatedTPM, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, &tc.cluster, &tc.metadata, &tc.cloudControllerManager, &tc.cloudNodeManager, &tc.clusterAutoscaler, nil, zapLogger, simulator.OpenSimulatedTPM, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
kubeconfig, err := core.InitCluster(tc.autoscalingNodeGroups, "cloud-service-account-uri")
|
kubeconfig, err := core.InitCluster(tc.autoscalingNodeGroups, "cloud-service-account-uri")
|
||||||
@ -286,7 +288,8 @@ func TestJoinCluster(t *testing.T) {
|
|||||||
|
|
||||||
zapLogger, err := zap.NewDevelopment()
|
zapLogger, err := zap.NewDevelopment()
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
core, err := NewCore(&tc.vpn, &tc.cluster, &tc.metadata, &tc.cloudControllerManager, &tc.cloudNodeManager, &tc.clusterAutoscaler, nil, zapLogger, simulator.OpenSimulatedTPM, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&tc.vpn, &tc.cluster, &tc.metadata, &tc.cloudControllerManager, &tc.cloudNodeManager, &tc.clusterAutoscaler, nil, zapLogger, simulator.OpenSimulatedTPM, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
joinReq := &kubeadm.BootstrapTokenDiscovery{
|
joinReq := &kubeadm.BootstrapTokenDiscovery{
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
||||||
"github.com/edgelesssys/constellation/coordinator/config"
|
"github.com/edgelesssys/constellation/coordinator/config"
|
||||||
"github.com/edgelesssys/constellation/coordinator/nodestate"
|
"github.com/edgelesssys/constellation/coordinator/nodestate"
|
||||||
@ -18,6 +17,8 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/store"
|
"github.com/edgelesssys/constellation/coordinator/store"
|
||||||
"github.com/edgelesssys/constellation/coordinator/storewrapper"
|
"github.com/edgelesssys/constellation/coordinator/storewrapper"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util"
|
"github.com/edgelesssys/constellation/coordinator/util"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/edgelesssys/constellation/kms/kms"
|
"github.com/edgelesssys/constellation/kms/kms"
|
||||||
kmsSetup "github.com/edgelesssys/constellation/kms/server/setup"
|
kmsSetup "github.com/edgelesssys/constellation/kms/server/setup"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@ -44,12 +45,13 @@ type Core struct {
|
|||||||
initialVPNPeersRetriever initialVPNPeersRetriever
|
initialVPNPeersRetriever initialVPNPeersRetriever
|
||||||
lastHeartbeats map[string]time.Time
|
lastHeartbeats map[string]time.Time
|
||||||
fileHandler file.Handler
|
fileHandler file.Handler
|
||||||
|
linuxUserManager user.LinuxUserManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCore creates and initializes a new Core object.
|
// NewCore creates and initializes a new Core object.
|
||||||
func NewCore(vpn VPN, kube Cluster,
|
func NewCore(vpn VPN, kube Cluster,
|
||||||
metadata ProviderMetadata, cloudControllerManager CloudControllerManager, cloudNodeManager CloudNodeManager, clusterAutoscaler ClusterAutoscaler,
|
metadata ProviderMetadata, cloudControllerManager CloudControllerManager, cloudNodeManager CloudNodeManager, clusterAutoscaler ClusterAutoscaler,
|
||||||
encryptedDisk EncryptedDisk, zapLogger *zap.Logger, openTPM vtpm.TPMOpenFunc, persistentStoreFactory PersistentStoreFactory, fileHandler file.Handler,
|
encryptedDisk EncryptedDisk, zapLogger *zap.Logger, openTPM vtpm.TPMOpenFunc, persistentStoreFactory PersistentStoreFactory, fileHandler file.Handler, linuxUserManager user.LinuxUserManager,
|
||||||
) (*Core, error) {
|
) (*Core, error) {
|
||||||
stor := store.NewStdStore()
|
stor := store.NewStdStore()
|
||||||
c := &Core{
|
c := &Core{
|
||||||
@ -68,6 +70,7 @@ func NewCore(vpn VPN, kube Cluster,
|
|||||||
initialVPNPeersRetriever: getInitialVPNPeers,
|
initialVPNPeersRetriever: getInitialVPNPeers,
|
||||||
lastHeartbeats: make(map[string]time.Time),
|
lastHeartbeats: make(map[string]time.Time),
|
||||||
fileHandler: fileHandler,
|
fileHandler: fileHandler,
|
||||||
|
linuxUserManager: linuxUserManager,
|
||||||
}
|
}
|
||||||
if err := c.data().IncrementPeersResourceVersion(); err != nil {
|
if err := c.data().IncrementPeersResourceVersion(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
||||||
"github.com/edgelesssys/constellation/coordinator/nodestate"
|
"github.com/edgelesssys/constellation/coordinator/nodestate"
|
||||||
@ -16,6 +15,8 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/store"
|
"github.com/edgelesssys/constellation/coordinator/store"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -36,7 +37,8 @@ func TestGetNextNodeIP(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
require.NoError(core.InitializeStoreIPs())
|
require.NoError(core.InitializeStoreIPs())
|
||||||
|
|
||||||
@ -79,7 +81,8 @@ func TestSwitchToPersistentStore(t *testing.T) {
|
|||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
storeFactory := &fakeStoreFactory{}
|
storeFactory := &fakeStoreFactory{}
|
||||||
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, storeFactory, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, storeFactory, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(core.store.Put("test", []byte("test")))
|
require.NoError(core.store.Put("test", []byte("test")))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
@ -93,7 +96,8 @@ func TestGetIDs(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
_, _, err = core.GetIDs(nil)
|
_, _, err = core.GetIDs(nil)
|
||||||
@ -117,7 +121,8 @@ func TestNotifyNodeHeartbeat(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
const ip = "192.0.2.1"
|
const ip = "192.0.2.1"
|
||||||
@ -130,7 +135,8 @@ func TestDeriveKey(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
// error when no kms is set up
|
// error when no kms is set up
|
||||||
@ -200,14 +206,15 @@ func TestInitialize(t *testing.T) {
|
|||||||
if tc.initializePCRs {
|
if tc.initializePCRs {
|
||||||
require.NoError(vtpm.MarkNodeAsInitialized(openTPM, []byte{0x0, 0x1, 0x2, 0x3}, []byte{0x4, 0x5, 0x6, 0x7}))
|
require.NoError(vtpm.MarkNodeAsInitialized(openTPM, []byte{0x0, 0x1, 0x2, 0x3}, []byte{0x4, 0x5, 0x6, 0x7}))
|
||||||
}
|
}
|
||||||
fileHandler := file.NewHandler(afero.NewMemMapFs())
|
fs := afero.NewMemMapFs()
|
||||||
|
fileHandler := file.NewHandler(fs)
|
||||||
if tc.writeNodeState {
|
if tc.writeNodeState {
|
||||||
require.NoError((&nodestate.NodeState{
|
require.NoError((&nodestate.NodeState{
|
||||||
Role: tc.role,
|
Role: tc.role,
|
||||||
VPNPrivKey: []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7},
|
VPNPrivKey: []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7},
|
||||||
}).ToFile(fileHandler))
|
}).ToFile(fileHandler))
|
||||||
}
|
}
|
||||||
core, err := NewCore(&stubVPN{}, nil, &ProviderMetadataFake{}, nil, nil, nil, nil, zaptest.NewLogger(t), openTPM, &fakeStoreFactory{}, fileHandler)
|
core, err := NewCore(&stubVPN{}, nil, &ProviderMetadataFake{}, nil, nil, nil, nil, zaptest.NewLogger(t), openTPM, &fakeStoreFactory{}, fileHandler, user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
core.initialVPNPeersRetriever = fakeInitializeVPNPeersRetriever
|
core.initialVPNPeersRetriever = fakeInitializeVPNPeersRetriever
|
||||||
// prepare store to emulate initialized KMS
|
// prepare store to emulate initialized KMS
|
||||||
@ -265,7 +272,7 @@ func TestPersistNodeState(t *testing.T) {
|
|||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
require.NoError(file.Close())
|
require.NoError(file.Close())
|
||||||
}
|
}
|
||||||
core, err := NewCore(tc.vpn, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, fileHandler)
|
core, err := NewCore(tc.vpn, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, fileHandler, user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
err = core.PersistNodeState(role.Coordinator, "192.0.2.1", []byte("owner-id"), []byte("cluster-id"))
|
err = core.PersistNodeState(role.Coordinator, "192.0.2.1", []byte("owner-id"), []byte("cluster-id"))
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
|
@ -4,7 +4,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -43,7 +44,8 @@ func TestGetDiskUUID(t *testing.T) {
|
|||||||
uuidErr: tc.uuidErr,
|
uuidErr: tc.uuidErr,
|
||||||
uuid: tc.wantUUID,
|
uuid: tc.wantUUID,
|
||||||
}
|
}
|
||||||
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, &diskStub, zapLogger, nil, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, &diskStub, zapLogger, nil, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
uuid, err := core.GetDiskUUID()
|
uuid, err := core.GetDiskUUID()
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
@ -85,7 +87,8 @@ func TestUpdateDiskPassphrase(t *testing.T) {
|
|||||||
openErr: tc.openErr,
|
openErr: tc.openErr,
|
||||||
updatePassphraseErr: tc.updatePassphraseErr,
|
updatePassphraseErr: tc.updatePassphraseErr,
|
||||||
}
|
}
|
||||||
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, &diskStub, zapLogger, nil, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, &diskStub, zapLogger, nil, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
err = core.UpdateDiskPassphrase("passphrase")
|
err = core.UpdateDiskPassphrase("passphrase")
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/atls"
|
"github.com/edgelesssys/constellation/coordinator/atls"
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
||||||
"github.com/edgelesssys/constellation/coordinator/pubapi"
|
"github.com/edgelesssys/constellation/coordinator/pubapi"
|
||||||
@ -18,6 +17,8 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
||||||
"github.com/edgelesssys/constellation/coordinator/vpnapi"
|
"github.com/edgelesssys/constellation/coordinator/vpnapi"
|
||||||
"github.com/edgelesssys/constellation/coordinator/vpnapi/vpnproto"
|
"github.com/edgelesssys/constellation/coordinator/vpnapi/vpnproto"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -131,7 +132,8 @@ func newMockCoreWithDialer(bufDialer *bufconnDialer) (*Core, *pubapi.API, error)
|
|||||||
getPublicAddr := func() (string, error) {
|
getPublicAddr := func() (string, error) {
|
||||||
return "192.0.2.1", nil
|
return "192.0.2.1", nil
|
||||||
}
|
}
|
||||||
core, err := NewCore(vpn, kubeFake, metadataFake, ccmFake, cnmFake, autoscalerFake, encryptedDiskFake, zapLogger, simulator.OpenSimulatedTPM, &fakeStoreFactory{}, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(vpn, kubeFake, metadataFake, ccmFake, cnmFake, autoscalerFake, encryptedDiskFake, zapLogger, simulator.OpenSimulatedTPM, &fakeStoreFactory{}, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/peer"
|
"github.com/edgelesssys/constellation/coordinator/peer"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -53,7 +54,8 @@ func TestGetPeers(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
// prepare store
|
// prepare store
|
||||||
@ -113,7 +115,8 @@ func TestAddPeer(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
core, err := NewCore(&tc.vpn, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&tc.vpn, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
|
|
||||||
err = core.AddPeer(tc.peer)
|
err = core.AddPeer(tc.peer)
|
||||||
|
@ -5,13 +5,14 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/atls"
|
"github.com/edgelesssys/constellation/coordinator/atls"
|
||||||
"github.com/edgelesssys/constellation/coordinator/peer"
|
"github.com/edgelesssys/constellation/coordinator/peer"
|
||||||
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
|
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
|
||||||
"github.com/edgelesssys/constellation/coordinator/role"
|
"github.com/edgelesssys/constellation/coordinator/role"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -79,7 +80,8 @@ func TestReinitializeAsNode(t *testing.T) {
|
|||||||
go server.Serve(netDialer.GetListener("192.0.2.1:9000"))
|
go server.Serve(netDialer.GetListener("192.0.2.1:9000"))
|
||||||
defer server.Stop()
|
defer server.Stop()
|
||||||
vpn := &stubVPN{}
|
vpn := &stubVPN{}
|
||||||
core, err := NewCore(vpn, nil, &stubMetadata{listRes: coordinators, supportedRes: true}, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(vpn, nil, &stubMetadata{listRes: coordinators, supportedRes: true}, nil, nil, nil, nil, zaptest.NewLogger(t), nil, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
err = core.ReinitializeAsNode(context.Background(), dialer, vpnIP, &stubPubAPI{}, 0)
|
err = core.ReinitializeAsNode(context.Background(), dialer, vpnIP, &stubPubAPI{}, 0)
|
||||||
|
|
||||||
@ -151,7 +153,8 @@ func TestReinitializeAsCoordinator(t *testing.T) {
|
|||||||
go server.Serve(netDialer.GetListener("192.0.2.1:9000"))
|
go server.Serve(netDialer.GetListener("192.0.2.1:9000"))
|
||||||
defer server.Stop()
|
defer server.Stop()
|
||||||
vpn := &stubVPN{}
|
vpn := &stubVPN{}
|
||||||
core, err := NewCore(vpn, nil, &stubMetadata{listRes: coordinators, supportedRes: true}, nil, nil, nil, nil, zaptest.NewLogger(t), nil, &fakeStoreFactory{}, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(vpn, nil, &stubMetadata{listRes: coordinators, supportedRes: true}, nil, nil, nil, nil, zaptest.NewLogger(t), nil, &fakeStoreFactory{}, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
// prepare store to emulate initialized KMS
|
// prepare store to emulate initialized KMS
|
||||||
require.NoError(core.data().PutKMSData(kms.KMSInformation{StorageUri: kms.NoStoreURI, KmsUri: kms.ClusterKMSURI}))
|
require.NoError(core.data().PutKMSData(kms.KMSInformation{StorageUri: kms.NoStoreURI, KmsUri: kms.ClusterKMSURI}))
|
||||||
|
21
coordinator/core/ssh.go
Normal file
21
coordinator/core/ssh.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateSSHUsers creates UNIX users with respective SSH access on the system the coordinator is running on when defined in the config.
|
||||||
|
func (c *Core) CreateSSHUsers(sshUserKeys []ssh.UserKey) error {
|
||||||
|
sshAccess := ssh.NewSSHAccess(c.linuxUserManager)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
for _, pair := range sshUserKeys {
|
||||||
|
if err := sshAccess.DeploySSHAuthorizedKey(ctx, pair); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -5,9 +5,10 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
"github.com/edgelesssys/constellation/coordinator/attestation/simulator"
|
||||||
"github.com/edgelesssys/constellation/coordinator/state"
|
"github.com/edgelesssys/constellation/coordinator/state"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -65,7 +66,8 @@ func TestAdvanceState(t *testing.T) {
|
|||||||
return simulator.OpenSimulatedTPM()
|
return simulator.OpenSimulatedTPM()
|
||||||
}
|
}
|
||||||
|
|
||||||
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), openTPM, nil, file.NewHandler(afero.NewMemMapFs()))
|
fs := afero.NewMemMapFs()
|
||||||
|
core, err := NewCore(&stubVPN{}, nil, nil, nil, nil, nil, nil, zaptest.NewLogger(t), openTPM, nil, file.NewHandler(fs), user.NewLinuxUserManagerFake(fs))
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
assert.Equal(state.Uninitialized, core.GetState())
|
assert.Equal(state.Uninitialized, core.GetState())
|
||||||
core.state = tc.initialState
|
core.state = tc.initialState
|
||||||
|
@ -3,8 +3,8 @@ package nodestate
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/role"
|
"github.com/edgelesssys/constellation/coordinator/role"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
const nodeStatePath = "/run/state/constellation/node_state.json"
|
const nodeStatePath = "/run/state/constellation/node_state.json"
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/role"
|
"github.com/edgelesssys/constellation/coordinator/role"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
|
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
|
||||||
"github.com/edgelesssys/constellation/coordinator/role"
|
"github.com/edgelesssys/constellation/coordinator/role"
|
||||||
"github.com/edgelesssys/constellation/coordinator/state"
|
"github.com/edgelesssys/constellation/coordinator/state"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
"github.com/edgelesssys/constellation/state/keyservice/keyproto"
|
"github.com/edgelesssys/constellation/state/keyservice/keyproto"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
@ -88,6 +89,15 @@ func (a *API) ActivateAsCoordinator(in *pubproto.ActivateAsCoordinatorRequest, s
|
|||||||
return status.Errorf(codes.Internal, "adding the coordinator to store/vpn: %v", err)
|
return status.Errorf(codes.Internal, "adding the coordinator to store/vpn: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup SSH users for the first coordinator, if defined
|
||||||
|
if len(in.SshUserKeys) != 0 {
|
||||||
|
logToCLI("Creating SSH users on first control-plane node...")
|
||||||
|
sshUserKeys := ssh.FromProtoSlice(in.SshUserKeys)
|
||||||
|
if err := a.core.CreateSSHUsers(sshUserKeys); err != nil {
|
||||||
|
return status.Errorf(codes.Internal, "creating SSH users: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logToCLI("Initializing Kubernetes ...")
|
logToCLI("Initializing Kubernetes ...")
|
||||||
kubeconfig, err := a.core.InitCluster(in.AutoscalingNodeGroups, in.CloudServiceAccountUri)
|
kubeconfig, err := a.core.InitCluster(in.AutoscalingNodeGroups, in.CloudServiceAccountUri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
@ -19,8 +20,11 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/state"
|
"github.com/edgelesssys/constellation/coordinator/state"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
"github.com/edgelesssys/constellation/coordinator/util/grpcutil"
|
||||||
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
"github.com/edgelesssys/constellation/coordinator/util/testdialer"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
||||||
"github.com/edgelesssys/constellation/state/keyservice/keyproto"
|
"github.com/edgelesssys/constellation/state/keyservice/keyproto"
|
||||||
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/zap/zaptest"
|
"go.uber.org/zap/zaptest"
|
||||||
@ -40,6 +44,14 @@ func TestActivateAsCoordinator(t *testing.T) {
|
|||||||
wantNode3 := peer.Peer{PublicIP: "192.0.2.13", VPNIP: "10.118.0.13", VPNPubKey: []byte{3, 4, 5}, Role: role.Node}
|
wantNode3 := peer.Peer{PublicIP: "192.0.2.13", VPNIP: "10.118.0.13", VPNPubKey: []byte{3, 4, 5}, Role: role.Node}
|
||||||
wantCoord := peer.Peer{PublicIP: "192.0.2.1", VPNIP: "10.118.0.1", VPNPubKey: coordinatorPubKey, Role: role.Coordinator}
|
wantCoord := peer.Peer{PublicIP: "192.0.2.1", VPNIP: "10.118.0.1", VPNPubKey: coordinatorPubKey, Role: role.Coordinator}
|
||||||
adminPeer := peer.Peer{VPNPubKey: []byte{7, 8, 9}, Role: role.Admin}
|
adminPeer := peer.Peer{VPNPubKey: []byte{7, 8, 9}, Role: role.Admin}
|
||||||
|
sshUser1 := &ssh.UserKey{
|
||||||
|
Username: "test-user-1",
|
||||||
|
PublicKey: "ssh-rsa abcdefg",
|
||||||
|
}
|
||||||
|
sshUser2 := &ssh.UserKey{
|
||||||
|
Username: "test-user-2",
|
||||||
|
PublicKey: "ssh-ed25519 hijklmn",
|
||||||
|
}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
nodes []*stubPeer
|
nodes []*stubPeer
|
||||||
@ -49,6 +61,7 @@ func TestActivateAsCoordinator(t *testing.T) {
|
|||||||
wantPeers []peer.Peer
|
wantPeers []peer.Peer
|
||||||
wantState state.State
|
wantState state.State
|
||||||
adminVPNIP string
|
adminVPNIP string
|
||||||
|
sshKeys []*ssh.UserKey
|
||||||
}{
|
}{
|
||||||
"0 nodes": {
|
"0 nodes": {
|
||||||
state: state.AcceptingInit,
|
state: state.AcceptingInit,
|
||||||
@ -77,6 +90,13 @@ func TestActivateAsCoordinator(t *testing.T) {
|
|||||||
wantState: state.ActivatingNodes,
|
wantState: state.ActivatingNodes,
|
||||||
adminVPNIP: "10.118.0.14",
|
adminVPNIP: "10.118.0.14",
|
||||||
},
|
},
|
||||||
|
"coordinator with SSH users": {
|
||||||
|
state: state.AcceptingInit,
|
||||||
|
wantPeers: []peer.Peer{wantCoord},
|
||||||
|
wantState: state.ActivatingNodes,
|
||||||
|
adminVPNIP: "10.118.0.11",
|
||||||
|
sshKeys: []*ssh.UserKey{sshUser1, sshUser2},
|
||||||
|
},
|
||||||
"already activated": {
|
"already activated": {
|
||||||
nodes: []*stubPeer{testNode1},
|
nodes: []*stubPeer{testNode1},
|
||||||
state: state.ActivatingNodes,
|
state: state.ActivatingNodes,
|
||||||
@ -117,7 +137,7 @@ func TestActivateAsCoordinator(t *testing.T) {
|
|||||||
|
|
||||||
autoscalingNodeGroups := []string{"ang1", "ang2"}
|
autoscalingNodeGroups := []string{"ang1", "ang2"}
|
||||||
keyEncryptionKeyID := "constellation"
|
keyEncryptionKeyID := "constellation"
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
core := &fakeCore{
|
core := &fakeCore{
|
||||||
state: tc.state,
|
state: tc.state,
|
||||||
vpnPubKey: coordinatorPubKey,
|
vpnPubKey: coordinatorPubKey,
|
||||||
@ -125,7 +145,9 @@ func TestActivateAsCoordinator(t *testing.T) {
|
|||||||
kubeconfig: []byte("kubeconfig"),
|
kubeconfig: []byte("kubeconfig"),
|
||||||
ownerID: []byte("ownerID"),
|
ownerID: []byte("ownerID"),
|
||||||
clusterID: []byte("clusterID"),
|
clusterID: []byte("clusterID"),
|
||||||
|
linuxUserManager: user.NewLinuxUserManagerFake(fs),
|
||||||
}
|
}
|
||||||
|
|
||||||
netDialer := testdialer.NewBufconnDialer()
|
netDialer := testdialer.NewBufconnDialer()
|
||||||
dialer := grpcutil.NewDialer(fakeValidator{}, netDialer)
|
dialer := grpcutil.NewDialer(fakeValidator{}, netDialer)
|
||||||
|
|
||||||
@ -162,6 +184,7 @@ func TestActivateAsCoordinator(t *testing.T) {
|
|||||||
UseExistingKek: false,
|
UseExistingKek: false,
|
||||||
KmsUri: kms.ClusterKMSURI,
|
KmsUri: kms.ClusterKMSURI,
|
||||||
StorageUri: kms.NoStoreURI,
|
StorageUri: kms.NoStoreURI,
|
||||||
|
SshUserKeys: ssh.ToProtoSlice(tc.sshKeys),
|
||||||
}, stream)
|
}, stream)
|
||||||
|
|
||||||
assert.Equal(tc.wantState, core.state)
|
assert.Equal(tc.wantState, core.state)
|
||||||
@ -194,6 +217,25 @@ func TestActivateAsCoordinator(t *testing.T) {
|
|||||||
assert.Equal(autoscalingNodeGroups, core.autoscalingNodeGroups)
|
assert.Equal(autoscalingNodeGroups, core.autoscalingNodeGroups)
|
||||||
assert.Equal(keyEncryptionKeyID, core.kekID)
|
assert.Equal(keyEncryptionKeyID, core.kekID)
|
||||||
assert.Equal([]role.Role{role.Coordinator}, core.persistNodeStateRoles)
|
assert.Equal([]role.Role{role.Coordinator}, core.persistNodeStateRoles)
|
||||||
|
|
||||||
|
// Test SSH user & key creation. Both cases: "supposed to add" and "not supposed to add"
|
||||||
|
// This slightly differs from a real environment (e.g. missing /home) but should be fine in the stub context with a virtual file system
|
||||||
|
if tc.sshKeys != nil {
|
||||||
|
passwd := user.Passwd{}
|
||||||
|
entries, err := passwd.Parse(fs)
|
||||||
|
require.NoError(err)
|
||||||
|
for _, singleEntry := range entries {
|
||||||
|
username := singleEntry.Gecos
|
||||||
|
_, err := fs.Stat(fmt.Sprintf("/home/%s/.ssh/authorized_keys.d/ssh-keys", username))
|
||||||
|
assert.NoError(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
passwd := user.Passwd{}
|
||||||
|
_, err := passwd.Parse(fs)
|
||||||
|
assert.EqualError(err, "open /etc/passwd: file does not exist")
|
||||||
|
_, err = fs.Stat("/home")
|
||||||
|
assert.EqualError(err, "open /home: file does not exist")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/peer"
|
"github.com/edgelesssys/constellation/coordinator/peer"
|
||||||
"github.com/edgelesssys/constellation/coordinator/role"
|
"github.com/edgelesssys/constellation/coordinator/role"
|
||||||
"github.com/edgelesssys/constellation/coordinator/state"
|
"github.com/edgelesssys/constellation/coordinator/state"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
||||||
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
)
|
)
|
||||||
@ -36,6 +37,8 @@ type Core interface {
|
|||||||
AddPeerToVPN(peer.Peer) error
|
AddPeerToVPN(peer.Peer) error
|
||||||
UpdatePeers([]peer.Peer) error
|
UpdatePeers([]peer.Peer) error
|
||||||
|
|
||||||
|
CreateSSHUsers([]ssh.UserKey) error
|
||||||
|
|
||||||
InitCluster(autoscalingNodeGroups []string, cloudServiceAccountURI string) ([]byte, error)
|
InitCluster(autoscalingNodeGroups []string, cloudServiceAccountURI string) ([]byte, error)
|
||||||
JoinCluster(joinToken *kubeadm.BootstrapTokenDiscovery, certificateKey string, role role.Role) error
|
JoinCluster(joinToken *kubeadm.BootstrapTokenDiscovery, certificateKey string, role role.Role) error
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/coordinator/peer"
|
"github.com/edgelesssys/constellation/coordinator/peer"
|
||||||
"github.com/edgelesssys/constellation/coordinator/role"
|
"github.com/edgelesssys/constellation/coordinator/role"
|
||||||
"github.com/edgelesssys/constellation/coordinator/state"
|
"github.com/edgelesssys/constellation/coordinator/state"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
kms "github.com/edgelesssys/constellation/kms/server/setup"
|
||||||
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
|
||||||
)
|
)
|
||||||
@ -36,6 +38,7 @@ type fakeCore struct {
|
|||||||
kekID string
|
kekID string
|
||||||
dataKey []byte
|
dataKey []byte
|
||||||
getDataKeyErr error
|
getDataKeyErr error
|
||||||
|
linuxUserManager user.LinuxUserManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fakeCore) GetVPNPubKey() ([]byte, error) {
|
func (c *fakeCore) GetVPNPubKey() ([]byte, error) {
|
||||||
@ -154,3 +157,16 @@ func (c *fakeCore) GetDiskUUID() (string, error) {
|
|||||||
func (c *fakeCore) UpdateDiskPassphrase(passphrase string) error {
|
func (c *fakeCore) UpdateDiskPassphrase(passphrase string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *fakeCore) CreateSSHUsers(sshUserKeys []ssh.UserKey) error {
|
||||||
|
sshAccess := ssh.NewSSHAccess(c.linuxUserManager)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
for _, pair := range sshUserKeys {
|
||||||
|
if err := sshAccess.DeploySSHAuthorizedKey(ctx, pair); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -110,16 +110,17 @@ type ActivateAsCoordinatorRequest struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
AdminVpnPubKey []byte `protobuf:"bytes,1,opt,name=admin_vpn_pub_key,json=adminVpnPubKey,proto3" json:"admin_vpn_pub_key,omitempty"`
|
AdminVpnPubKey []byte `protobuf:"bytes,1,opt,name=admin_vpn_pub_key,json=adminVpnPubKey,proto3" json:"admin_vpn_pub_key,omitempty"`
|
||||||
NodePublicIps []string `protobuf:"bytes,2,rep,name=node_public_ips,json=nodePublicIps,proto3" json:"node_public_ips,omitempty"`
|
NodePublicIps []string `protobuf:"bytes,2,rep,name=node_public_ips,json=nodePublicIps,proto3" json:"node_public_ips,omitempty"`
|
||||||
CoordinatorPublicIps []string `protobuf:"bytes,3,rep,name=coordinator_public_ips,json=coordinatorPublicIps,proto3" json:"coordinator_public_ips,omitempty"`
|
CoordinatorPublicIps []string `protobuf:"bytes,3,rep,name=coordinator_public_ips,json=coordinatorPublicIps,proto3" json:"coordinator_public_ips,omitempty"`
|
||||||
AutoscalingNodeGroups []string `protobuf:"bytes,4,rep,name=autoscaling_node_groups,json=autoscalingNodeGroups,proto3" json:"autoscaling_node_groups,omitempty"`
|
AutoscalingNodeGroups []string `protobuf:"bytes,4,rep,name=autoscaling_node_groups,json=autoscalingNodeGroups,proto3" json:"autoscaling_node_groups,omitempty"`
|
||||||
MasterSecret []byte `protobuf:"bytes,5,opt,name=master_secret,json=masterSecret,proto3" json:"master_secret,omitempty"`
|
MasterSecret []byte `protobuf:"bytes,5,opt,name=master_secret,json=masterSecret,proto3" json:"master_secret,omitempty"`
|
||||||
KmsUri string `protobuf:"bytes,6,opt,name=kms_uri,json=kmsUri,proto3" json:"kms_uri,omitempty"`
|
KmsUri string `protobuf:"bytes,6,opt,name=kms_uri,json=kmsUri,proto3" json:"kms_uri,omitempty"`
|
||||||
StorageUri string `protobuf:"bytes,7,opt,name=storage_uri,json=storageUri,proto3" json:"storage_uri,omitempty"`
|
StorageUri string `protobuf:"bytes,7,opt,name=storage_uri,json=storageUri,proto3" json:"storage_uri,omitempty"`
|
||||||
KeyEncryptionKeyId string `protobuf:"bytes,8,opt,name=key_encryption_key_id,json=keyEncryptionKeyId,proto3" json:"key_encryption_key_id,omitempty"`
|
KeyEncryptionKeyId string `protobuf:"bytes,8,opt,name=key_encryption_key_id,json=keyEncryptionKeyId,proto3" json:"key_encryption_key_id,omitempty"`
|
||||||
UseExistingKek bool `protobuf:"varint,9,opt,name=use_existing_kek,json=useExistingKek,proto3" json:"use_existing_kek,omitempty"`
|
UseExistingKek bool `protobuf:"varint,9,opt,name=use_existing_kek,json=useExistingKek,proto3" json:"use_existing_kek,omitempty"`
|
||||||
CloudServiceAccountUri string `protobuf:"bytes,10,opt,name=cloud_service_account_uri,json=cloudServiceAccountUri,proto3" json:"cloud_service_account_uri,omitempty"`
|
CloudServiceAccountUri string `protobuf:"bytes,10,opt,name=cloud_service_account_uri,json=cloudServiceAccountUri,proto3" json:"cloud_service_account_uri,omitempty"`
|
||||||
|
SshUserKeys []*SSHUserKey `protobuf:"bytes,11,rep,name=ssh_user_keys,json=sshUserKeys,proto3" json:"ssh_user_keys,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ActivateAsCoordinatorRequest) Reset() {
|
func (x *ActivateAsCoordinatorRequest) Reset() {
|
||||||
@ -224,6 +225,13 @@ func (x *ActivateAsCoordinatorRequest) GetCloudServiceAccountUri() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *ActivateAsCoordinatorRequest) GetSshUserKeys() []*SSHUserKey {
|
||||||
|
if x != nil {
|
||||||
|
return x.SshUserKeys
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type ActivateAsCoordinatorResponse struct {
|
type ActivateAsCoordinatorResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -1520,6 +1528,61 @@ func (x *Peer) GetRole() uint32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SSHUserKey struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
|
||||||
|
PublicKey string `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SSHUserKey) Reset() {
|
||||||
|
*x = SSHUserKey{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_pubapi_proto_msgTypes[28]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SSHUserKey) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SSHUserKey) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *SSHUserKey) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_pubapi_proto_msgTypes[28]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use SSHUserKey.ProtoReflect.Descriptor instead.
|
||||||
|
func (*SSHUserKey) Descriptor() ([]byte, []int) {
|
||||||
|
return file_pubapi_proto_rawDescGZIP(), []int{28}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SSHUserKey) GetUsername() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Username
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SSHUserKey) GetPublicKey() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.PublicKey
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
var File_pubapi_proto protoreflect.FileDescriptor
|
var File_pubapi_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_pubapi_proto_rawDesc = []byte{
|
var file_pubapi_proto_rawDesc = []byte{
|
||||||
@ -1528,7 +1591,7 @@ var file_pubapi_proto_rawDesc = []byte{
|
|||||||
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x28, 0x0a, 0x10, 0x47, 0x65, 0x74,
|
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x28, 0x0a, 0x10, 0x47, 0x65, 0x74,
|
||||||
0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a,
|
0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a,
|
||||||
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x74,
|
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x74,
|
||||||
0x61, 0x74, 0x65, 0x22, 0xd6, 0x03, 0x0a, 0x1c, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
|
0x61, 0x74, 0x65, 0x22, 0x8e, 0x04, 0x0a, 0x1c, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
|
||||||
0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71,
|
0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x11, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x70,
|
0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x11, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x70,
|
||||||
0x6e, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
0x6e, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||||
@ -1557,209 +1620,217 @@ var file_pubapi_proto_rawDesc = []byte{
|
|||||||
0x6b, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69,
|
0x6b, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69,
|
||||||
0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x0a,
|
0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x0a,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||||
0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x72, 0x69, 0x22, 0x85, 0x01, 0x0a,
|
0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x55, 0x72, 0x69, 0x12, 0x36, 0x0a, 0x0d,
|
||||||
0x1d, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64,
|
0x73, 0x73, 0x68, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x0b, 0x20,
|
||||||
0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38,
|
0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x53, 0x48,
|
||||||
0x0a, 0x0c, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01,
|
0x55, 0x73, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x0b, 0x73, 0x73, 0x68, 0x55, 0x73, 0x65, 0x72,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64,
|
0x4b, 0x65, 0x79, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x1d, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
|
||||||
0x6d, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x64, 0x6d,
|
0x65, 0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65,
|
||||||
0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0c, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x4c,
|
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70,
|
||||||
0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e,
|
0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x74, 0x65, 0x6e, 0x74, 0x22, 0x9b, 0x01, 0x0a, 0x15, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
|
0x67, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f,
|
0x12, 0x1f, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e,
|
||||||
0x0a, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f,
|
||||||
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69,
|
0x67, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x9b, 0x01, 0x0a,
|
||||||
0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x49,
|
0x15, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x52,
|
||||||
0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52,
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
|
||||||
0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
0x6c, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x26, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x6b, 0x65,
|
0x24, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
|
||||||
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x65,
|
0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65,
|
||||||
0x44, 0x69, 0x73, 0x6b, 0x4b, 0x65, 0x79, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
|
||||||
0x73, 0x74, 0x22, 0x9c, 0x01, 0x0a, 0x1c, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x65,
|
||||||
0x73, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75,
|
0x5f, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48,
|
||||||
0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x76, 0x70, 0x6e, 0x5f,
|
0x00, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x6b, 0x4b, 0x65, 0x79, 0x42,
|
||||||
0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x56, 0x70,
|
0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x9c, 0x01, 0x0a, 0x1c, 0x41,
|
||||||
0x6e, 0x49, 0x70, 0x12, 0x22, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03,
|
0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x69,
|
||||||
0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x65, 0x65, 0x72,
|
0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x6e,
|
||||||
0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72,
|
0x6f, 0x64, 0x65, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72,
|
0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x56, 0x70, 0x6e, 0x49, 0x70, 0x12, 0x22, 0x0a, 0x05, 0x70,
|
||||||
0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64,
|
0x65, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x75, 0x62,
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49,
|
0x61, 0x70, 0x69, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x12,
|
||||||
0x64, 0x22, 0x79, 0x0a, 0x16, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x4e,
|
0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x6e,
|
0x0c, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c,
|
||||||
0x6f, 0x64, 0x65, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18,
|
0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x56, 0x70, 0x6e,
|
0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x79, 0x0a, 0x16, 0x41, 0x63, 0x74,
|
||||||
0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f,
|
0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
0x64, 0x69, 0x73, 0x6b, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48,
|
0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x76, 0x70, 0x6e, 0x5f,
|
||||||
0x00, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x6b, 0x55, 0x75, 0x69, 0x64,
|
0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52,
|
||||||
0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x48, 0x0a, 0x1e,
|
0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x56, 0x70, 0x6e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x28,
|
||||||
0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x75, 0x75, 0x69,
|
||||||
0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26,
|
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x65,
|
||||||
0x0a, 0x0f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x70,
|
0x44, 0x69, 0x73, 0x6b, 0x55, 0x75, 0x69, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70,
|
||||||
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x50, 0x75, 0x62,
|
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x48, 0x0a, 0x1e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
|
||||||
0x6c, 0x69, 0x63, 0x49, 0x70, 0x73, 0x22, 0x40, 0x0a, 0x1f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61,
|
0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52,
|
||||||
0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65,
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x70,
|
||||||
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x03, 0x6c, 0x6f, 0x67,
|
0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e,
|
0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x70, 0x73, 0x22, 0x40,
|
||||||
0x4c, 0x6f, 0x67, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x22, 0xfc, 0x01, 0x0a, 0x26, 0x41, 0x63, 0x74,
|
0x0a, 0x1f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69,
|
||||||
0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61,
|
0x6f, 0x6e, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||||
0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75,
|
0x65, 0x12, 0x1d, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b,
|
||||||
0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f,
|
0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x6f, 0x67, 0x52, 0x03, 0x6c, 0x6f, 0x67,
|
||||||
0x76, 0x70, 0x6e, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x73,
|
0x22, 0xfc, 0x01, 0x0a, 0x26, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x41,
|
||||||
0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x70, 0x6e, 0x49, 0x70, 0x12, 0x4c, 0x0a, 0x1b, 0x61,
|
|
||||||
0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69,
|
|
||||||
0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
|
||||||
0x32, 0x0c, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x19,
|
|
||||||
0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69,
|
|
||||||
0x6e, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x05, 0x70, 0x65, 0x65,
|
|
||||||
0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70,
|
|
||||||
0x69, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x12, 0x19, 0x0a,
|
|
||||||
0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
|
||||||
0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73,
|
|
||||||
0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x6c,
|
|
||||||
0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x29, 0x0a, 0x27, 0x41, 0x63, 0x74, 0x69, 0x76,
|
|
||||||
0x61, 0x74, 0x65, 0x41, 0x73, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43,
|
|
||||||
0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
|
||||||
0x73, 0x65, 0x22, 0x5a, 0x0a, 0x24, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64,
|
|
||||||
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61,
|
|
||||||
0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f,
|
|
||||||
0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
|
||||||
0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x6f, 0x72, 0x64,
|
|
||||||
0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x70, 0x22, 0x27,
|
|
||||||
0x0a, 0x25, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69,
|
|
||||||
0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52,
|
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, 0x0a, 0x12, 0x4a, 0x6f, 0x69, 0x6e, 0x43,
|
|
||||||
0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a,
|
|
||||||
0x12, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x76, 0x70, 0x6e,
|
|
||||||
0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6f, 0x72, 0x64,
|
|
||||||
0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x70, 0x6e, 0x49, 0x70, 0x22, 0x15, 0x0a, 0x13, 0x4a,
|
|
||||||
0x6f, 0x69, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
|
||||||
0x73, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4e, 0x6f, 0x64,
|
|
||||||
0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x1b,
|
|
||||||
0x0a, 0x19, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x55, 0x70, 0x64,
|
|
||||||
0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x0a, 0x1f, 0x54,
|
|
||||||
0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f,
|
|
||||||
0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x22,
|
|
||||||
0x0a, 0x20, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e,
|
|
||||||
0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
|
||||||
0x73, 0x65, 0x22, 0x39, 0x0a, 0x1a, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61,
|
|
||||||
0x74, 0x65, 0x44, 0x69, 0x73, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
|
||||||
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x55, 0x75, 0x69, 0x64, 0x22, 0x1d, 0x0a,
|
|
||||||
0x1b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73,
|
|
||||||
0x6b, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x0a, 0x1a,
|
|
||||||
0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x56, 0x50, 0x4e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
|
||||||
0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4d, 0x0a, 0x1b, 0x47, 0x65,
|
|
||||||
0x74, 0x50, 0x65, 0x65, 0x72, 0x56, 0x50, 0x4e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65,
|
|
||||||
0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6f, 0x6f,
|
|
||||||
0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79,
|
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61,
|
|
||||||
0x74, 0x6f, 0x72, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x22, 0x14, 0x0a, 0x12, 0x47, 0x65, 0x74,
|
|
||||||
0x56, 0x50, 0x4e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
|
|
||||||
0x39, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x56, 0x50, 0x4e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65,
|
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18,
|
|
||||||
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x50,
|
|
||||||
0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x41,
|
|
||||||
0x64, 0x6d, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0c, 0x61, 0x64,
|
|
||||||
0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
|
||||||
0x52, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x70, 0x6e, 0x49, 0x70, 0x12, 0x35, 0x0a, 0x17,
|
|
||||||
0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x76, 0x70, 0x6e, 0x5f,
|
|
||||||
0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x63,
|
|
||||||
0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x70, 0x6e, 0x50, 0x75, 0x62,
|
|
||||||
0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69,
|
|
||||||
0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e,
|
|
||||||
0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18,
|
|
||||||
0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d,
|
|
||||||
0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01,
|
|
||||||
0x28, 0x0c, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x1f, 0x0a,
|
|
||||||
0x03, 0x4c, 0x6f, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
|
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x6e,
|
|
||||||
0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
|
||||||
0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69,
|
|
||||||
0x63, 0x49, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x70, 0x6e, 0x5f, 0x69, 0x70, 0x18, 0x02, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x70, 0x6e, 0x49, 0x70, 0x12, 0x1e, 0x0a, 0x0b, 0x76, 0x70,
|
|
||||||
0x6e, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
|
||||||
0x09, 0x76, 0x70, 0x6e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f,
|
|
||||||
0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x32, 0x8b,
|
|
||||||
0x09, 0x0a, 0x03, 0x41, 0x50, 0x49, 0x12, 0x3d, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61,
|
|
||||||
0x74, 0x65, 0x12, 0x17, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53,
|
|
||||||
0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x75,
|
|
||||||
0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
|
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
|
|
||||||
0x65, 0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x24,
|
|
||||||
0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
|
|
||||||
0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71,
|
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63,
|
|
||||||
0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61,
|
|
||||||
0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a,
|
|
||||||
0x0e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12,
|
|
||||||
0x1d, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
|
|
||||||
0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e,
|
|
||||||
0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
|
|
||||||
0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01,
|
|
||||||
0x30, 0x01, 0x12, 0x6c, 0x0a, 0x17, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64,
|
|
||||||
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x26, 0x2e,
|
|
||||||
0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41,
|
|
||||||
0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65,
|
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41,
|
|
||||||
0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61,
|
|
||||||
0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01,
|
|
||||||
0x12, 0x82, 0x01, 0x0a, 0x1f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x41,
|
|
||||||
0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e,
|
0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e,
|
||||||
0x61, 0x74, 0x6f, 0x72, 0x12, 0x2e, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63,
|
0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x61,
|
||||||
0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x69, 0x70, 0x18, 0x01,
|
||||||
0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x70,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63,
|
0x6e, 0x49, 0x70, 0x12, 0x4c, 0x0a, 0x1b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6e,
|
||||||
0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
0x67, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x61,
|
||||||
0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73,
|
0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x1d, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
|
0x69, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x19, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69,
|
||||||
0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64,
|
0x6e, 0x67, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x44, 0x61, 0x74,
|
||||||
0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2c, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e,
|
0x61, 0x12, 0x22, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
0x32, 0x0c, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05,
|
||||||
0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71,
|
0x70, 0x65, 0x65, 0x72, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63,
|
0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64,
|
||||||
|
0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05,
|
||||||
|
0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x64, 0x22,
|
||||||
|
0x29, 0x0a, 0x27, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x41, 0x64, 0x64,
|
||||||
|
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74,
|
||||||
|
0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5a, 0x0a, 0x24, 0x41, 0x63,
|
||||||
0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
|
0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
|
||||||
0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x4a, 0x6f, 0x69, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74,
|
0x73, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f,
|
||||||
0x65, 0x72, 0x12, 0x1a, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x4a, 0x6f, 0x69, 0x6e,
|
0x72, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b,
|
0x09, 0x52, 0x13, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x75,
|
||||||
0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x43, 0x6c, 0x75, 0x73,
|
0x62, 0x6c, 0x69, 0x63, 0x49, 0x70, 0x22, 0x27, 0x0a, 0x25, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61,
|
||||||
0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x54,
|
0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72,
|
||||||
0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
0x12, 0x20, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65,
|
0x42, 0x0a, 0x12, 0x4a, 0x6f, 0x69, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65,
|
||||||
0x72, 0x4e, 0x6f, 0x64, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e,
|
||||||
0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x69, 0x67,
|
0x61, 0x74, 0x6f, 0x72, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x67, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
|
0x09, 0x52, 0x10, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x56, 0x70,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x18, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
|
0x6e, 0x49, 0x70, 0x22, 0x15, 0x0a, 0x13, 0x4a, 0x6f, 0x69, 0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74,
|
||||||
0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74,
|
0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x54, 0x72,
|
||||||
0x65, 0x12, 0x27, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67,
|
0x69, 0x67, 0x67, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
|
||||||
0x65, 0x72, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64,
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x1b, 0x0a, 0x19, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65,
|
||||||
0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x75, 0x62,
|
0x72, 0x4e, 0x6f, 0x64, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6f, 0x72, 0x64,
|
0x6e, 0x73, 0x65, 0x22, 0x21, 0x0a, 0x1f, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f,
|
||||||
0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70,
|
0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x56,
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x22, 0x0a, 0x20, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65,
|
||||||
0x50, 0x4e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x22, 0x2e, 0x70, 0x75,
|
0x72, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61,
|
||||||
0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x56, 0x50, 0x4e, 0x50,
|
0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x0a, 0x1a, 0x52, 0x65,
|
||||||
0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x6b, 0x4b, 0x65,
|
||||||
0x23, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72,
|
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b,
|
||||||
0x56, 0x50, 0x4e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70,
|
0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x69, 0x73,
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x56, 0x50, 0x4e, 0x50, 0x65,
|
0x6b, 0x55, 0x75, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x65, 0x72, 0x73, 0x12, 0x1a, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74,
|
0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70,
|
||||||
0x56, 0x50, 0x4e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x56,
|
||||||
0x1b, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x50, 0x4e, 0x50,
|
0x50, 0x4e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x13,
|
0x73, 0x74, 0x22, 0x4d, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x56, 0x50, 0x4e,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x6b,
|
0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||||
0x4b, 0x65, 0x79, 0x12, 0x22, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x71,
|
0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x6b, 0x4b, 0x65, 0x79,
|
0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69,
|
0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x50, 0x75, 0x62, 0x4b, 0x65,
|
||||||
0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73,
|
0x79, 0x22, 0x14, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x56, 0x50, 0x4e, 0x50, 0x65, 0x65, 0x72, 0x73,
|
||||||
0x6b, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x42, 0x5a, 0x40,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x39, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x56, 0x50,
|
||||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x64, 0x67, 0x65, 0x6c,
|
0x4e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22,
|
||||||
0x65, 0x73, 0x73, 0x73, 0x79, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x6c, 0x6c, 0x61,
|
0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72,
|
0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65,
|
||||||
0x2f, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x72, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66,
|
||||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x69, 0x67, 0x12, 0x20, 0x0a, 0x0c, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x76, 0x70, 0x6e, 0x5f,
|
||||||
|
0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x56,
|
||||||
|
0x70, 0x6e, 0x49, 0x70, 0x12, 0x35, 0x0a, 0x17, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61,
|
||||||
|
0x74, 0x6f, 0x72, 0x5f, 0x76, 0x70, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18,
|
||||||
|
0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74,
|
||||||
|
0x6f, 0x72, 0x56, 0x70, 0x6e, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x6b,
|
||||||
|
0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||||
|
0x0a, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x6f,
|
||||||
|
0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f,
|
||||||
|
0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
|
||||||
|
0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73,
|
||||||
|
0x74, 0x65, 0x72, 0x49, 0x64, 0x22, 0x1f, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x18, 0x0a, 0x07,
|
||||||
|
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d,
|
||||||
|
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x6e, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x1b,
|
||||||
|
0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x76,
|
||||||
|
0x70, 0x6e, 0x5f, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x70, 0x6e,
|
||||||
|
0x49, 0x70, 0x12, 0x1e, 0x0a, 0x0b, 0x76, 0x70, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x5f, 0x6b, 0x65,
|
||||||
|
0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x76, 0x70, 0x6e, 0x50, 0x75, 0x62, 0x4b,
|
||||||
|
0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d,
|
||||||
|
0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0a, 0x53, 0x53, 0x48, 0x55, 0x73, 0x65,
|
||||||
|
0x72, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
|
||||||
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
|
||||||
|
0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02,
|
||||||
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x32,
|
||||||
|
0x8b, 0x09, 0x0a, 0x03, 0x41, 0x50, 0x49, 0x12, 0x3d, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74,
|
||||||
|
0x61, 0x74, 0x65, 0x12, 0x17, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74,
|
||||||
|
0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x70,
|
||||||
|
0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65,
|
||||||
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61,
|
||||||
|
0x74, 0x65, 0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12,
|
||||||
|
0x24, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
|
||||||
|
0x65, 0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65,
|
||||||
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41,
|
||||||
|
0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e,
|
||||||
|
0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x53,
|
||||||
|
0x0a, 0x0e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65,
|
||||||
|
0x12, 0x1d, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61,
|
||||||
|
0x74, 0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
|
0x1e, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
|
||||||
|
0x65, 0x41, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28,
|
||||||
|
0x01, 0x30, 0x01, 0x12, 0x6c, 0x0a, 0x17, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41,
|
||||||
|
0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x26,
|
||||||
|
0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
|
||||||
|
0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52,
|
||||||
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e,
|
||||||
|
0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
|
0x61, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30,
|
||||||
|
0x01, 0x12, 0x82, 0x01, 0x0a, 0x1f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73,
|
||||||
|
0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69,
|
||||||
|
0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2e, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41,
|
||||||
|
0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65,
|
||||||
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41,
|
||||||
|
0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x73, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65,
|
||||||
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x1d, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61,
|
||||||
|
0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72,
|
||||||
|
0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x2c, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69,
|
||||||
|
0x2e, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x61, 0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65,
|
||||||
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x41,
|
||||||
|
0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61,
|
||||||
|
0x6c, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70,
|
||||||
|
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x4a, 0x6f, 0x69, 0x6e, 0x43, 0x6c, 0x75, 0x73,
|
||||||
|
0x74, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x4a, 0x6f, 0x69,
|
||||||
|
0x6e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
|
0x1b, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x43, 0x6c, 0x75,
|
||||||
|
0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x11,
|
||||||
|
0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||||
|
0x65, 0x12, 0x20, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67,
|
||||||
|
0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75,
|
||||||
|
0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x69,
|
||||||
|
0x67, 0x67, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65,
|
||||||
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x18, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65,
|
||||||
|
0x72, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61,
|
||||||
|
0x74, 0x65, 0x12, 0x27, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x69, 0x67,
|
||||||
|
0x67, 0x65, 0x72, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70,
|
||||||
|
0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x75,
|
||||||
|
0x62, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6f, 0x72,
|
||||||
|
0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
|
||||||
|
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72,
|
||||||
|
0x56, 0x50, 0x4e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x22, 0x2e, 0x70,
|
||||||
|
0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x56, 0x50, 0x4e,
|
||||||
|
0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
|
0x1a, 0x23, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65,
|
||||||
|
0x72, 0x56, 0x50, 0x4e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73,
|
||||||
|
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x56, 0x50, 0x4e, 0x50,
|
||||||
|
0x65, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65,
|
||||||
|
0x74, 0x56, 0x50, 0x4e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
|
0x1a, 0x1b, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x50, 0x4e,
|
||||||
|
0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a,
|
||||||
|
0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73,
|
||||||
|
0x6b, 0x4b, 0x65, 0x79, 0x12, 0x22, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65,
|
||||||
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x6b, 0x4b, 0x65,
|
||||||
|
0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x75, 0x62, 0x61, 0x70,
|
||||||
|
0x69, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69,
|
||||||
|
0x73, 0x6b, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x42, 0x5a,
|
||||||
|
0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x64, 0x67, 0x65,
|
||||||
|
0x6c, 0x65, 0x73, 0x73, 0x73, 0x79, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x6c, 0x6c,
|
||||||
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x6f,
|
||||||
|
0x72, 0x2f, 0x70, 0x75, 0x62, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x75, 0x62, 0x70, 0x72, 0x6f, 0x74,
|
||||||
|
0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -1774,7 +1845,7 @@ func file_pubapi_proto_rawDescGZIP() []byte {
|
|||||||
return file_pubapi_proto_rawDescData
|
return file_pubapi_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_pubapi_proto_msgTypes = make([]protoimpl.MessageInfo, 28)
|
var file_pubapi_proto_msgTypes = make([]protoimpl.MessageInfo, 29)
|
||||||
var file_pubapi_proto_goTypes = []interface{}{
|
var file_pubapi_proto_goTypes = []interface{}{
|
||||||
(*GetStateRequest)(nil), // 0: pubapi.GetStateRequest
|
(*GetStateRequest)(nil), // 0: pubapi.GetStateRequest
|
||||||
(*GetStateResponse)(nil), // 1: pubapi.GetStateResponse
|
(*GetStateResponse)(nil), // 1: pubapi.GetStateResponse
|
||||||
@ -1804,45 +1875,47 @@ var file_pubapi_proto_goTypes = []interface{}{
|
|||||||
(*AdminConfig)(nil), // 25: pubapi.AdminConfig
|
(*AdminConfig)(nil), // 25: pubapi.AdminConfig
|
||||||
(*Log)(nil), // 26: pubapi.Log
|
(*Log)(nil), // 26: pubapi.Log
|
||||||
(*Peer)(nil), // 27: pubapi.Peer
|
(*Peer)(nil), // 27: pubapi.Peer
|
||||||
|
(*SSHUserKey)(nil), // 28: pubapi.SSHUserKey
|
||||||
}
|
}
|
||||||
var file_pubapi_proto_depIdxs = []int32{
|
var file_pubapi_proto_depIdxs = []int32{
|
||||||
25, // 0: pubapi.ActivateAsCoordinatorResponse.admin_config:type_name -> pubapi.AdminConfig
|
28, // 0: pubapi.ActivateAsCoordinatorRequest.ssh_user_keys:type_name -> pubapi.SSHUserKey
|
||||||
26, // 1: pubapi.ActivateAsCoordinatorResponse.log:type_name -> pubapi.Log
|
25, // 1: pubapi.ActivateAsCoordinatorResponse.admin_config:type_name -> pubapi.AdminConfig
|
||||||
5, // 2: pubapi.ActivateAsNodeRequest.initial_request:type_name -> pubapi.ActivateAsNodeInitialRequest
|
26, // 2: pubapi.ActivateAsCoordinatorResponse.log:type_name -> pubapi.Log
|
||||||
27, // 3: pubapi.ActivateAsNodeInitialRequest.peers:type_name -> pubapi.Peer
|
5, // 3: pubapi.ActivateAsNodeRequest.initial_request:type_name -> pubapi.ActivateAsNodeInitialRequest
|
||||||
26, // 4: pubapi.ActivateAdditionalNodesResponse.log:type_name -> pubapi.Log
|
27, // 4: pubapi.ActivateAsNodeInitialRequest.peers:type_name -> pubapi.Peer
|
||||||
27, // 5: pubapi.ActivateAsAdditionalCoordinatorRequest.activating_coordinator_data:type_name -> pubapi.Peer
|
26, // 5: pubapi.ActivateAdditionalNodesResponse.log:type_name -> pubapi.Log
|
||||||
27, // 6: pubapi.ActivateAsAdditionalCoordinatorRequest.peers:type_name -> pubapi.Peer
|
27, // 6: pubapi.ActivateAsAdditionalCoordinatorRequest.activating_coordinator_data:type_name -> pubapi.Peer
|
||||||
27, // 7: pubapi.GetVPNPeersResponse.peers:type_name -> pubapi.Peer
|
27, // 7: pubapi.ActivateAsAdditionalCoordinatorRequest.peers:type_name -> pubapi.Peer
|
||||||
0, // 8: pubapi.API.GetState:input_type -> pubapi.GetStateRequest
|
27, // 8: pubapi.GetVPNPeersResponse.peers:type_name -> pubapi.Peer
|
||||||
2, // 9: pubapi.API.ActivateAsCoordinator:input_type -> pubapi.ActivateAsCoordinatorRequest
|
0, // 9: pubapi.API.GetState:input_type -> pubapi.GetStateRequest
|
||||||
4, // 10: pubapi.API.ActivateAsNode:input_type -> pubapi.ActivateAsNodeRequest
|
2, // 10: pubapi.API.ActivateAsCoordinator:input_type -> pubapi.ActivateAsCoordinatorRequest
|
||||||
7, // 11: pubapi.API.ActivateAdditionalNodes:input_type -> pubapi.ActivateAdditionalNodesRequest
|
4, // 11: pubapi.API.ActivateAsNode:input_type -> pubapi.ActivateAsNodeRequest
|
||||||
9, // 12: pubapi.API.ActivateAsAdditionalCoordinator:input_type -> pubapi.ActivateAsAdditionalCoordinatorRequest
|
7, // 12: pubapi.API.ActivateAdditionalNodes:input_type -> pubapi.ActivateAdditionalNodesRequest
|
||||||
11, // 13: pubapi.API.ActivateAdditionalCoordinator:input_type -> pubapi.ActivateAdditionalCoordinatorRequest
|
9, // 13: pubapi.API.ActivateAsAdditionalCoordinator:input_type -> pubapi.ActivateAsAdditionalCoordinatorRequest
|
||||||
13, // 14: pubapi.API.JoinCluster:input_type -> pubapi.JoinClusterRequest
|
11, // 14: pubapi.API.ActivateAdditionalCoordinator:input_type -> pubapi.ActivateAdditionalCoordinatorRequest
|
||||||
15, // 15: pubapi.API.TriggerNodeUpdate:input_type -> pubapi.TriggerNodeUpdateRequest
|
13, // 15: pubapi.API.JoinCluster:input_type -> pubapi.JoinClusterRequest
|
||||||
17, // 16: pubapi.API.TriggerCoordinatorUpdate:input_type -> pubapi.TriggerCoordinatorUpdateRequest
|
15, // 16: pubapi.API.TriggerNodeUpdate:input_type -> pubapi.TriggerNodeUpdateRequest
|
||||||
21, // 17: pubapi.API.GetPeerVPNPublicKey:input_type -> pubapi.GetPeerVPNPublicKeyRequest
|
17, // 17: pubapi.API.TriggerCoordinatorUpdate:input_type -> pubapi.TriggerCoordinatorUpdateRequest
|
||||||
23, // 18: pubapi.API.GetVPNPeers:input_type -> pubapi.GetVPNPeersRequest
|
21, // 18: pubapi.API.GetPeerVPNPublicKey:input_type -> pubapi.GetPeerVPNPublicKeyRequest
|
||||||
19, // 19: pubapi.API.RequestStateDiskKey:input_type -> pubapi.RequestStateDiskKeyRequest
|
23, // 19: pubapi.API.GetVPNPeers:input_type -> pubapi.GetVPNPeersRequest
|
||||||
1, // 20: pubapi.API.GetState:output_type -> pubapi.GetStateResponse
|
19, // 20: pubapi.API.RequestStateDiskKey:input_type -> pubapi.RequestStateDiskKeyRequest
|
||||||
3, // 21: pubapi.API.ActivateAsCoordinator:output_type -> pubapi.ActivateAsCoordinatorResponse
|
1, // 21: pubapi.API.GetState:output_type -> pubapi.GetStateResponse
|
||||||
6, // 22: pubapi.API.ActivateAsNode:output_type -> pubapi.ActivateAsNodeResponse
|
3, // 22: pubapi.API.ActivateAsCoordinator:output_type -> pubapi.ActivateAsCoordinatorResponse
|
||||||
8, // 23: pubapi.API.ActivateAdditionalNodes:output_type -> pubapi.ActivateAdditionalNodesResponse
|
6, // 23: pubapi.API.ActivateAsNode:output_type -> pubapi.ActivateAsNodeResponse
|
||||||
10, // 24: pubapi.API.ActivateAsAdditionalCoordinator:output_type -> pubapi.ActivateAsAdditionalCoordinatorResponse
|
8, // 24: pubapi.API.ActivateAdditionalNodes:output_type -> pubapi.ActivateAdditionalNodesResponse
|
||||||
12, // 25: pubapi.API.ActivateAdditionalCoordinator:output_type -> pubapi.ActivateAdditionalCoordinatorResponse
|
10, // 25: pubapi.API.ActivateAsAdditionalCoordinator:output_type -> pubapi.ActivateAsAdditionalCoordinatorResponse
|
||||||
14, // 26: pubapi.API.JoinCluster:output_type -> pubapi.JoinClusterResponse
|
12, // 26: pubapi.API.ActivateAdditionalCoordinator:output_type -> pubapi.ActivateAdditionalCoordinatorResponse
|
||||||
16, // 27: pubapi.API.TriggerNodeUpdate:output_type -> pubapi.TriggerNodeUpdateResponse
|
14, // 27: pubapi.API.JoinCluster:output_type -> pubapi.JoinClusterResponse
|
||||||
18, // 28: pubapi.API.TriggerCoordinatorUpdate:output_type -> pubapi.TriggerCoordinatorUpdateResponse
|
16, // 28: pubapi.API.TriggerNodeUpdate:output_type -> pubapi.TriggerNodeUpdateResponse
|
||||||
22, // 29: pubapi.API.GetPeerVPNPublicKey:output_type -> pubapi.GetPeerVPNPublicKeyResponse
|
18, // 29: pubapi.API.TriggerCoordinatorUpdate:output_type -> pubapi.TriggerCoordinatorUpdateResponse
|
||||||
24, // 30: pubapi.API.GetVPNPeers:output_type -> pubapi.GetVPNPeersResponse
|
22, // 30: pubapi.API.GetPeerVPNPublicKey:output_type -> pubapi.GetPeerVPNPublicKeyResponse
|
||||||
20, // 31: pubapi.API.RequestStateDiskKey:output_type -> pubapi.RequestStateDiskKeyResponse
|
24, // 31: pubapi.API.GetVPNPeers:output_type -> pubapi.GetVPNPeersResponse
|
||||||
20, // [20:32] is the sub-list for method output_type
|
20, // 32: pubapi.API.RequestStateDiskKey:output_type -> pubapi.RequestStateDiskKeyResponse
|
||||||
8, // [8:20] is the sub-list for method input_type
|
21, // [21:33] is the sub-list for method output_type
|
||||||
8, // [8:8] is the sub-list for extension type_name
|
9, // [9:21] is the sub-list for method input_type
|
||||||
8, // [8:8] is the sub-list for extension extendee
|
9, // [9:9] is the sub-list for extension type_name
|
||||||
0, // [0:8] is the sub-list for field type_name
|
9, // [9:9] is the sub-list for extension extendee
|
||||||
|
0, // [0:9] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_pubapi_proto_init() }
|
func init() { file_pubapi_proto_init() }
|
||||||
@ -2187,6 +2260,18 @@ func file_pubapi_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
file_pubapi_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*SSHUserKey); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
file_pubapi_proto_msgTypes[3].OneofWrappers = []interface{}{
|
file_pubapi_proto_msgTypes[3].OneofWrappers = []interface{}{
|
||||||
(*ActivateAsCoordinatorResponse_AdminConfig)(nil),
|
(*ActivateAsCoordinatorResponse_AdminConfig)(nil),
|
||||||
@ -2206,7 +2291,7 @@ func file_pubapi_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_pubapi_proto_rawDesc,
|
RawDescriptor: file_pubapi_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 28,
|
NumMessages: 29,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
@ -37,6 +37,7 @@ message ActivateAsCoordinatorRequest {
|
|||||||
string key_encryption_key_id = 8;
|
string key_encryption_key_id = 8;
|
||||||
bool use_existing_kek = 9;
|
bool use_existing_kek = 9;
|
||||||
string cloud_service_account_uri = 10;
|
string cloud_service_account_uri = 10;
|
||||||
|
repeated SSHUserKey ssh_user_keys = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ActivateAsCoordinatorResponse {
|
message ActivateAsCoordinatorResponse {
|
||||||
@ -152,3 +153,8 @@ message Peer {
|
|||||||
bytes vpn_pub_key = 3;
|
bytes vpn_pub_key = 3;
|
||||||
uint32 role = 4;
|
uint32 role = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SSHUserKey {
|
||||||
|
string username = 1;
|
||||||
|
string public_key = 2;
|
||||||
|
}
|
||||||
|
@ -8,16 +8,16 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/debugd/cdbg/config"
|
"github.com/edgelesssys/constellation/debugd/cdbg/config"
|
||||||
"github.com/edgelesssys/constellation/debugd/cdbg/state"
|
"github.com/edgelesssys/constellation/debugd/cdbg/state"
|
||||||
"github.com/edgelesssys/constellation/debugd/coordinator"
|
"github.com/edgelesssys/constellation/debugd/coordinator"
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd"
|
"github.com/edgelesssys/constellation/debugd/debugd"
|
||||||
depl "github.com/edgelesssys/constellation/debugd/debugd/deploy"
|
depl "github.com/edgelesssys/constellation/debugd/debugd/deploy"
|
||||||
pb "github.com/edgelesssys/constellation/debugd/service"
|
pb "github.com/edgelesssys/constellation/debugd/service"
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
|
||||||
configc "github.com/edgelesssys/constellation/internal/config"
|
configc "github.com/edgelesssys/constellation/internal/config"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
statec "github.com/edgelesssys/constellation/internal/state"
|
statec "github.com/edgelesssys/constellation/internal/state"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -105,7 +105,7 @@ type deployOnEndpointInput struct {
|
|||||||
debugdEndpoint string
|
debugdEndpoint string
|
||||||
coordinatorPath string
|
coordinatorPath string
|
||||||
reader fileToStreamReader
|
reader fileToStreamReader
|
||||||
authorizedKeys []ssh.SSHKey
|
authorizedKeys []ssh.UserKey
|
||||||
systemdUnits []depl.SystemdUnit
|
systemdUnits []depl.SystemdUnit
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ func deployOnEndpoint(ctx context.Context, in deployOnEndpointInput) error {
|
|||||||
for _, key := range in.authorizedKeys {
|
for _, key := range in.authorizedKeys {
|
||||||
pbKeys = append(pbKeys, &pb.AuthorizedKey{
|
pbKeys = append(pbKeys, &pb.AuthorizedKey{
|
||||||
Username: key.Username,
|
Username: key.Username,
|
||||||
KeyValue: key.KeyValue,
|
KeyValue: key.PublicKey,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
authorizedKeysResponse, err := client.UploadAuthorizedKeys(ctx, &pb.UploadAuthorizedKeysRequest{Keys: pbKeys}, grpc.WaitForReady(true))
|
authorizedKeysResponse, err := client.UploadAuthorizedKeys(ctx, &pb.UploadAuthorizedKeysRequest{Keys: pbKeys}, grpc.WaitForReady(true))
|
||||||
|
@ -5,9 +5,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/deploy"
|
"github.com/edgelesssys/constellation/debugd/debugd/deploy"
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CDBGConfig describes the constellation-cli config file.
|
// CDBGConfig describes the constellation-cli config file.
|
||||||
@ -17,7 +17,7 @@ type CDBGConfig struct {
|
|||||||
|
|
||||||
// ConstellationDebugdConfig is the cdbg specific configuration.
|
// ConstellationDebugdConfig is the cdbg specific configuration.
|
||||||
type ConstellationDebugdConfig struct {
|
type ConstellationDebugdConfig struct {
|
||||||
AuthorizedKeys []ssh.SSHKey `yaml:"authorizedKeys"`
|
AuthorizedKeys []ssh.UserKey `yaml:"authorizedKeys"`
|
||||||
CoordinatorPath string `yaml:"coordinatorPath"`
|
CoordinatorPath string `yaml:"coordinatorPath"`
|
||||||
SystemdUnits []deploy.SystemdUnit `yaml:"systemdUnits,omitempty"`
|
SystemdUnits []deploy.SystemdUnit `yaml:"systemdUnits,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/debugd/debugd/metadata/cloudprovider"
|
"github.com/edgelesssys/constellation/debugd/debugd/metadata/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/metadata/fallback"
|
"github.com/edgelesssys/constellation/debugd/debugd/metadata/fallback"
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/server"
|
"github.com/edgelesssys/constellation/debugd/debugd/server"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
@ -20,9 +22,10 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
|
|
||||||
streamer := coordinator.NewFileStreamer(afero.NewOsFs())
|
fs := afero.NewOsFs()
|
||||||
|
streamer := coordinator.NewFileStreamer(fs)
|
||||||
serviceManager := deploy.NewServiceManager()
|
serviceManager := deploy.NewServiceManager()
|
||||||
ssh := deploy.NewSSHAccess(afero.NewOsFs())
|
ssh := ssh.NewSSHAccess(user.NewLinuxUserManager(fs))
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
package deploy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/deploy/createuser"
|
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/deploy/passwd"
|
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrUserDoesNotExist is returned by GetLinuxUser if a linux user does not exist yet.
|
|
||||||
var ErrUserDoesNotExist = errors.New("user does not exist")
|
|
||||||
|
|
||||||
type passwdParser interface {
|
|
||||||
Parse(fs afero.Fs) (passwd.Entries, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type userCreator interface {
|
|
||||||
CreateUser(ctx context.Context, username string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// LinuxUser holds relevant information about a linux user (subset of /etc/passwd).
|
|
||||||
type LinuxUser struct {
|
|
||||||
Username string
|
|
||||||
Home string
|
|
||||||
Uid int
|
|
||||||
Gid int
|
|
||||||
}
|
|
||||||
|
|
||||||
// LinuxUserManager can retrieve information on linux users and create new users.
|
|
||||||
type LinuxUserManager struct {
|
|
||||||
fs afero.Fs
|
|
||||||
passwd passwdParser
|
|
||||||
creator userCreator
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewLinuxUserManager creates a new LinuxUserManager.
|
|
||||||
func NewLinuxUserManager(fs afero.Fs) *LinuxUserManager {
|
|
||||||
return &LinuxUserManager{
|
|
||||||
fs: fs,
|
|
||||||
passwd: passwd.Passwd{},
|
|
||||||
creator: createuser.Unix{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getLinuxUser tries to find an existing linux user in /etc/passwd.
|
|
||||||
func (l *LinuxUserManager) getLinuxUser(username string) (LinuxUser, error) {
|
|
||||||
entries, err := l.passwd.Parse(l.fs)
|
|
||||||
if err != nil {
|
|
||||||
return LinuxUser{}, err
|
|
||||||
}
|
|
||||||
if _, ok := entries[username]; !ok {
|
|
||||||
return LinuxUser{}, ErrUserDoesNotExist
|
|
||||||
}
|
|
||||||
entry := entries[username]
|
|
||||||
uid, err := strconv.Atoi(entry.Uid)
|
|
||||||
if err != nil {
|
|
||||||
return LinuxUser{}, fmt.Errorf("failed to parse users uid: %w", err)
|
|
||||||
}
|
|
||||||
gid, err := strconv.Atoi(entry.Gid)
|
|
||||||
if err != nil {
|
|
||||||
return LinuxUser{}, fmt.Errorf("failed to parse users gid: %w", err)
|
|
||||||
}
|
|
||||||
return LinuxUser{
|
|
||||||
Username: username,
|
|
||||||
Home: entry.Home,
|
|
||||||
Uid: uid,
|
|
||||||
Gid: gid,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnsureLinuxUserExists will try to create the user specified by username and call GetLinuxUser to retrieve user information.
|
|
||||||
func (l *LinuxUserManager) EnsureLinuxUserExists(ctx context.Context, username string) (LinuxUser, error) {
|
|
||||||
// try to create user (even if it already exists)
|
|
||||||
if err := l.creator.CreateUser(ctx, username); err != nil {
|
|
||||||
return LinuxUser{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return l.getLinuxUser(username)
|
|
||||||
}
|
|
@ -7,7 +7,7 @@ import (
|
|||||||
azurecloud "github.com/edgelesssys/constellation/coordinator/cloudprovider/azure"
|
azurecloud "github.com/edgelesssys/constellation/coordinator/cloudprovider/azure"
|
||||||
gcpcloud "github.com/edgelesssys/constellation/coordinator/cloudprovider/gcp"
|
gcpcloud "github.com/edgelesssys/constellation/coordinator/cloudprovider/gcp"
|
||||||
"github.com/edgelesssys/constellation/coordinator/core"
|
"github.com/edgelesssys/constellation/coordinator/core"
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
type providerMetadata interface {
|
type providerMetadata interface {
|
||||||
@ -72,16 +72,16 @@ func (f *Fetcher) DiscoverDebugdIPs(ctx context.Context) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FetchSSHKeys will query the metadata of the current instance and deploys any SSH keys found.
|
// FetchSSHKeys will query the metadata of the current instance and deploys any SSH keys found.
|
||||||
func (f *Fetcher) FetchSSHKeys(ctx context.Context) ([]ssh.SSHKey, error) {
|
func (f *Fetcher) FetchSSHKeys(ctx context.Context) ([]ssh.UserKey, error) {
|
||||||
self, err := f.metaAPI.Self(ctx)
|
self, err := f.metaAPI.Self(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("retrieving ssh keys from cloud provider metadata failed: %w", err)
|
return nil, fmt.Errorf("retrieving ssh keys from cloud provider metadata failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
keys := []ssh.SSHKey{}
|
keys := []ssh.UserKey{}
|
||||||
for username, userKeys := range self.SSHKeys {
|
for username, userKeys := range self.SSHKeys {
|
||||||
for _, keyValue := range userKeys {
|
for _, keyValue := range userKeys {
|
||||||
keys = append(keys, ssh.SSHKey{Username: username, KeyValue: keyValue})
|
keys = append(keys, ssh.UserKey{Username: username, PublicKey: keyValue})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/core"
|
"github.com/edgelesssys/constellation/coordinator/core"
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@ -70,7 +70,7 @@ func TestFetchSSHKeys(t *testing.T) {
|
|||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
meta stubMetadata
|
meta stubMetadata
|
||||||
wantKeys []ssh.SSHKey
|
wantKeys []ssh.UserKey
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
"fetch works": {
|
"fetch works": {
|
||||||
@ -81,10 +81,10 @@ func TestFetchSSHKeys(t *testing.T) {
|
|||||||
SSHKeys: map[string][]string{"bob": {"ssh-rsa bobskey"}},
|
SSHKeys: map[string][]string{"bob": {"ssh-rsa bobskey"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantKeys: []ssh.SSHKey{
|
wantKeys: []ssh.UserKey{
|
||||||
{
|
{
|
||||||
Username: "bob",
|
Username: "bob",
|
||||||
KeyValue: "ssh-rsa bobskey",
|
PublicKey: "ssh-rsa bobskey",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@ package fallback
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fetcher implements metadata.Fetcher interface but does not actually fetch cloud provider metadata.
|
// Fetcher implements metadata.Fetcher interface but does not actually fetch cloud provider metadata.
|
||||||
@ -14,7 +14,7 @@ func (f Fetcher) DiscoverDebugdIPs(ctx context.Context) ([]string, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Fetcher) FetchSSHKeys(ctx context.Context) ([]ssh.SSHKey, error) {
|
func (f Fetcher) FetchSSHKeys(ctx context.Context) ([]ssh.UserKey, error) {
|
||||||
// Fallback fetcher does not try to fetch ssh keys
|
// Fallback fetcher does not try to fetch ssh keys
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd"
|
"github.com/edgelesssys/constellation/debugd/debugd"
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fetcher retrieves other debugd IPs and SSH keys from cloud provider metadata.
|
// Fetcher retrieves other debugd IPs and SSH keys from cloud provider metadata.
|
||||||
type Fetcher interface {
|
type Fetcher interface {
|
||||||
DiscoverDebugdIPs(ctx context.Context) ([]string, error)
|
DiscoverDebugdIPs(ctx context.Context) ([]string, error)
|
||||||
FetchSSHKeys(ctx context.Context) ([]ssh.SSHKey, error)
|
FetchSSHKeys(ctx context.Context) ([]ssh.UserKey, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scheduler schedules fetching of metadata using timers.
|
// Scheduler schedules fetching of metadata using timers.
|
||||||
@ -122,7 +122,7 @@ func (s *Scheduler) downloadCoordinator(ctx context.Context, ips []string) (succ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// deploySSHKeys tries to deploy a list of SSH keys and logs errors encountered.
|
// deploySSHKeys tries to deploy a list of SSH keys and logs errors encountered.
|
||||||
func (s *Scheduler) deploySSHKeys(ctx context.Context, keys []ssh.SSHKey) {
|
func (s *Scheduler) deploySSHKeys(ctx context.Context, keys []ssh.UserKey) {
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
err := s.ssh.DeploySSHAuthorizedKey(ctx, key)
|
err := s.ssh.DeploySSHAuthorizedKey(ctx, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -137,5 +137,5 @@ type downloader interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type sshDeployer interface {
|
type sshDeployer interface {
|
||||||
DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.SSHKey) error
|
DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.UserKey) error
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,23 +17,23 @@ func TestSchedulerStart(t *testing.T) {
|
|||||||
ssh stubSSHDeployer
|
ssh stubSSHDeployer
|
||||||
downloader stubDownloader
|
downloader stubDownloader
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
wantSSHKeys []ssh.SSHKey
|
wantSSHKeys []ssh.UserKey
|
||||||
wantDebugdDownloads []string
|
wantDebugdDownloads []string
|
||||||
}{
|
}{
|
||||||
"scheduler works and calls fetcher functions at least once": {},
|
"scheduler works and calls fetcher functions at least once": {},
|
||||||
"ssh keys are fetched": {
|
"ssh keys are fetched": {
|
||||||
fetcher: stubFetcher{
|
fetcher: stubFetcher{
|
||||||
keys: []ssh.SSHKey{
|
keys: []ssh.UserKey{
|
||||||
{
|
{
|
||||||
Username: "test",
|
Username: "test",
|
||||||
KeyValue: "testkey",
|
PublicKey: "testkey",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantSSHKeys: []ssh.SSHKey{
|
wantSSHKeys: []ssh.UserKey{
|
||||||
{
|
{
|
||||||
Username: "test",
|
Username: "test",
|
||||||
KeyValue: "testkey",
|
PublicKey: "testkey",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -95,7 +95,7 @@ type stubFetcher struct {
|
|||||||
fetchSSHKeysCalls int
|
fetchSSHKeysCalls int
|
||||||
|
|
||||||
ips []string
|
ips []string
|
||||||
keys []ssh.SSHKey
|
keys []ssh.UserKey
|
||||||
discoverErr error
|
discoverErr error
|
||||||
fetchSSHKeysErr error
|
fetchSSHKeysErr error
|
||||||
}
|
}
|
||||||
@ -105,18 +105,18 @@ func (s *stubFetcher) DiscoverDebugdIPs(ctx context.Context) ([]string, error) {
|
|||||||
return s.ips, s.discoverErr
|
return s.ips, s.discoverErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stubFetcher) FetchSSHKeys(ctx context.Context) ([]ssh.SSHKey, error) {
|
func (s *stubFetcher) FetchSSHKeys(ctx context.Context) ([]ssh.UserKey, error) {
|
||||||
s.fetchSSHKeysCalls++
|
s.fetchSSHKeysCalls++
|
||||||
return s.keys, s.fetchSSHKeysErr
|
return s.keys, s.fetchSSHKeysErr
|
||||||
}
|
}
|
||||||
|
|
||||||
type stubSSHDeployer struct {
|
type stubSSHDeployer struct {
|
||||||
sshKeys []ssh.SSHKey
|
sshKeys []ssh.UserKey
|
||||||
|
|
||||||
deployErr error
|
deployErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stubSSHDeployer) DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.SSHKey) error {
|
func (s *stubSSHDeployer) DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.UserKey) error {
|
||||||
s.sshKeys = append(s.sshKeys, sshKey)
|
s.sshKeys = append(s.sshKeys, sshKey)
|
||||||
|
|
||||||
return s.deployErr
|
return s.deployErr
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/debugd/debugd"
|
"github.com/edgelesssys/constellation/debugd/debugd"
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/deploy"
|
"github.com/edgelesssys/constellation/debugd/debugd/deploy"
|
||||||
pb "github.com/edgelesssys/constellation/debugd/service"
|
pb "github.com/edgelesssys/constellation/debugd/service"
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ func New(ssh sshDeployer, serviceManager serviceManager, streamer streamer) pb.D
|
|||||||
func (s *debugdServer) UploadAuthorizedKeys(ctx context.Context, in *pb.UploadAuthorizedKeysRequest) (*pb.UploadAuthorizedKeysResponse, error) {
|
func (s *debugdServer) UploadAuthorizedKeys(ctx context.Context, in *pb.UploadAuthorizedKeysRequest) (*pb.UploadAuthorizedKeysResponse, error) {
|
||||||
log.Println("Uploading authorized keys")
|
log.Println("Uploading authorized keys")
|
||||||
for _, key := range in.Keys {
|
for _, key := range in.Keys {
|
||||||
if err := s.ssh.DeploySSHAuthorizedKey(ctx, ssh.SSHKey{Username: key.Username, KeyValue: key.KeyValue}); err != nil {
|
if err := s.ssh.DeploySSHAuthorizedKey(ctx, ssh.UserKey{Username: key.Username, PublicKey: key.KeyValue}); err != nil {
|
||||||
log.Printf("Uploading authorized keys failed: %v\n", err)
|
log.Printf("Uploading authorized keys failed: %v\n", err)
|
||||||
return &pb.UploadAuthorizedKeysResponse{
|
return &pb.UploadAuthorizedKeysResponse{
|
||||||
Status: pb.UploadAuthorizedKeysStatus_UPLOAD_AUTHORIZED_KEYS_FAILURE,
|
Status: pb.UploadAuthorizedKeysStatus_UPLOAD_AUTHORIZED_KEYS_FAILURE,
|
||||||
@ -117,7 +117,7 @@ func Start(wg *sync.WaitGroup, serv pb.DebugdServer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type sshDeployer interface {
|
type sshDeployer interface {
|
||||||
DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.SSHKey) error
|
DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.UserKey) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type serviceManager interface {
|
type serviceManager interface {
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/debugd/coordinator"
|
"github.com/edgelesssys/constellation/debugd/coordinator"
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/deploy"
|
"github.com/edgelesssys/constellation/debugd/debugd/deploy"
|
||||||
pb "github.com/edgelesssys/constellation/debugd/service"
|
pb "github.com/edgelesssys/constellation/debugd/service"
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
@ -28,7 +28,7 @@ func TestUploadAuthorizedKeys(t *testing.T) {
|
|||||||
request *pb.UploadAuthorizedKeysRequest
|
request *pb.UploadAuthorizedKeysRequest
|
||||||
wantErr bool
|
wantErr bool
|
||||||
wantResponseStatus pb.UploadAuthorizedKeysStatus
|
wantResponseStatus pb.UploadAuthorizedKeysStatus
|
||||||
wantKeys []ssh.SSHKey
|
wantKeys []ssh.UserKey
|
||||||
}{
|
}{
|
||||||
"upload authorized keys works": {
|
"upload authorized keys works": {
|
||||||
request: &pb.UploadAuthorizedKeysRequest{
|
request: &pb.UploadAuthorizedKeysRequest{
|
||||||
@ -40,10 +40,10 @@ func TestUploadAuthorizedKeys(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantResponseStatus: pb.UploadAuthorizedKeysStatus_UPLOAD_AUTHORIZED_KEYS_SUCCESS,
|
wantResponseStatus: pb.UploadAuthorizedKeysStatus_UPLOAD_AUTHORIZED_KEYS_SUCCESS,
|
||||||
wantKeys: []ssh.SSHKey{
|
wantKeys: []ssh.UserKey{
|
||||||
{
|
{
|
||||||
Username: "testuser",
|
Username: "testuser",
|
||||||
KeyValue: "teskey",
|
PublicKey: "teskey",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -58,10 +58,10 @@ func TestUploadAuthorizedKeys(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ssh: stubSSHDeployer{deployErr: errors.New("ssh key deployment error")},
|
ssh: stubSSHDeployer{deployErr: errors.New("ssh key deployment error")},
|
||||||
wantResponseStatus: pb.UploadAuthorizedKeysStatus_UPLOAD_AUTHORIZED_KEYS_FAILURE,
|
wantResponseStatus: pb.UploadAuthorizedKeysStatus_UPLOAD_AUTHORIZED_KEYS_FAILURE,
|
||||||
wantKeys: []ssh.SSHKey{
|
wantKeys: []ssh.UserKey{
|
||||||
{
|
{
|
||||||
Username: "testuser",
|
Username: "testuser",
|
||||||
KeyValue: "teskey",
|
PublicKey: "teskey",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -323,12 +323,12 @@ func TestUploadSystemServiceUnits(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type stubSSHDeployer struct {
|
type stubSSHDeployer struct {
|
||||||
sshKeys []ssh.SSHKey
|
sshKeys []ssh.UserKey
|
||||||
|
|
||||||
deployErr error
|
deployErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stubSSHDeployer) DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.SSHKey) error {
|
func (s *stubSSHDeployer) DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.UserKey) error {
|
||||||
s.sshKeys = append(s.sshKeys, sshKey)
|
s.sshKeys = append(s.sshKeys, sshKey)
|
||||||
|
|
||||||
return s.deployErr
|
return s.deployErr
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package ssh
|
|
||||||
|
|
||||||
// SSHKey describes a public ssh key.
|
|
||||||
type SSHKey struct {
|
|
||||||
Username string `yaml:"user"`
|
|
||||||
KeyValue string `yaml:"pubkey"`
|
|
||||||
}
|
|
@ -9,10 +9,11 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
|
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
|
||||||
"github.com/edgelesssys/constellation/cli/ec2"
|
"github.com/edgelesssys/constellation/cli/ec2"
|
||||||
awsClient "github.com/edgelesssys/constellation/cli/ec2/client"
|
awsClient "github.com/edgelesssys/constellation/cli/ec2/client"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
gcpClient "github.com/edgelesssys/constellation/cli/gcp/client"
|
gcpClient "github.com/edgelesssys/constellation/cli/gcp/client"
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/deploy/ssh"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ type Config struct {
|
|||||||
AutoscalingNodeGroupsMax *int `yaml:"autoscalingNodeGroupsMax,omitempty"`
|
AutoscalingNodeGroupsMax *int `yaml:"autoscalingNodeGroupsMax,omitempty"`
|
||||||
StateDiskSizeGB *int `yaml:"StateDisksizeGB,omitempty"`
|
StateDiskSizeGB *int `yaml:"StateDisksizeGB,omitempty"`
|
||||||
Provider *ProviderConfig `yaml:"provider,omitempty"`
|
Provider *ProviderConfig `yaml:"provider,omitempty"`
|
||||||
|
SSHUsers []*ssh.UserKey `yaml:"sshUsers,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default returns a struct with the default config.
|
// Default returns a struct with the default config.
|
||||||
|
@ -4,9 +4,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
|
"github.com/edgelesssys/constellation/cli/cloud/cloudtypes"
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/cli/gcp/client"
|
"github.com/edgelesssys/constellation/cli/gcp/client"
|
||||||
"github.com/edgelesssys/constellation/internal/constants"
|
"github.com/edgelesssys/constellation/internal/constants"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
44
internal/deploy/ssh/proto.go
Normal file
44
internal/deploy/ssh/proto.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package ssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/edgelesssys/constellation/coordinator/pubapi/pubproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromProtoSlice converts a SSH UserKey definition from pubproto to the Go flavor.
|
||||||
|
func FromProtoSlice(input []*pubproto.SSHUserKey) []UserKey {
|
||||||
|
if input == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
output := make([]UserKey, 0)
|
||||||
|
|
||||||
|
for _, pair := range input {
|
||||||
|
singlePair := UserKey{
|
||||||
|
Username: pair.Username,
|
||||||
|
PublicKey: pair.PublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
output = append(output, singlePair)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToProtoSlice converts a SSH UserKey definition from Go to pubproto flavor.
|
||||||
|
func ToProtoSlice(input []*UserKey) []*pubproto.SSHUserKey {
|
||||||
|
if input == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
output := make([]*pubproto.SSHUserKey, 0)
|
||||||
|
for _, pair := range input {
|
||||||
|
singlePair := pubproto.SSHUserKey{
|
||||||
|
Username: pair.Username,
|
||||||
|
PublicKey: pair.PublicKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
output = append(output, &singlePair)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
36
internal/deploy/ssh/proto_test.go
Normal file
36
internal/deploy/ssh/proto_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package ssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestToAndFromProtoSlice(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
DemoSSHUser1 := UserKey{
|
||||||
|
Username: "test-user-2",
|
||||||
|
PublicKey: "ssh-rsa abcdefg",
|
||||||
|
}
|
||||||
|
|
||||||
|
DemoSSHUser2 := UserKey{
|
||||||
|
Username: "test-user-2",
|
||||||
|
PublicKey: "ssh-rsa hijklmnop",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input usually consists of pointers (from config parsing)
|
||||||
|
DemoSSHUsersPointers := make([]*UserKey, 0)
|
||||||
|
DemoSSHUsersPointers = append(DemoSSHUsersPointers, &DemoSSHUser1)
|
||||||
|
DemoSSHUsersPointers = append(DemoSSHUsersPointers, &DemoSSHUser2)
|
||||||
|
|
||||||
|
// Expected output usually does not consist of pointers
|
||||||
|
DemoSSHUsersNoPointers := make([]UserKey, 0)
|
||||||
|
DemoSSHUsersNoPointers = append(DemoSSHUsersNoPointers, DemoSSHUser1)
|
||||||
|
DemoSSHUsersNoPointers = append(DemoSSHUsersNoPointers, DemoSSHUser2)
|
||||||
|
|
||||||
|
ToProtoArray := ToProtoSlice(DemoSSHUsersPointers)
|
||||||
|
FromProtoArray := FromProtoSlice(ToProtoArray)
|
||||||
|
|
||||||
|
assert.Equal(DemoSSHUsersNoPointers, FromProtoArray)
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package deploy
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -7,46 +7,43 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/deploy/createuser"
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/deploy/passwd"
|
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
|
||||||
"github.com/spf13/afero"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// UserKey describes an user that should be created with a corresponding public SSH key.
|
||||||
|
type UserKey struct {
|
||||||
|
Username string `yaml:"user"`
|
||||||
|
PublicKey string `yaml:"pubkey"`
|
||||||
|
}
|
||||||
|
|
||||||
// SSHAccess reads ssh public keys from a channel, creates the specified users if required and writes the public keys to the users authorized_keys file.
|
// SSHAccess reads ssh public keys from a channel, creates the specified users if required and writes the public keys to the users authorized_keys file.
|
||||||
type SSHAccess struct {
|
type SSHAccess struct {
|
||||||
fs afero.Fs
|
userManager user.LinuxUserManager
|
||||||
userManager LinuxUserManager
|
|
||||||
authorized map[string]bool
|
authorized map[string]bool
|
||||||
mux sync.Mutex
|
mux sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSSHAccess creates a new SSHAccess.
|
// NewSSHAccess creates a new SSHAccess.
|
||||||
func NewSSHAccess(fs afero.Fs) *SSHAccess {
|
func NewSSHAccess(userManager user.LinuxUserManager) *SSHAccess {
|
||||||
return &SSHAccess{
|
return &SSHAccess{
|
||||||
fs: fs,
|
userManager: userManager,
|
||||||
userManager: LinuxUserManager{
|
mux: sync.Mutex{},
|
||||||
fs: fs,
|
authorized: map[string]bool{},
|
||||||
passwd: passwd.Passwd{},
|
|
||||||
creator: createuser.Unix{},
|
|
||||||
},
|
|
||||||
mux: sync.Mutex{},
|
|
||||||
authorized: map[string]bool{},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// alreadyAuthorized checks if key was written to authorized keys before.
|
// alreadyAuthorized checks if key was written to authorized keys before.
|
||||||
func (s *SSHAccess) alreadyAuthorized(sshKey ssh.SSHKey) bool {
|
func (s *SSHAccess) alreadyAuthorized(sshKey UserKey) bool {
|
||||||
_, ok := s.authorized[fmt.Sprintf("%s:%s", sshKey.Username, sshKey.KeyValue)]
|
_, ok := s.authorized[fmt.Sprintf("%s:%s", sshKey.Username, sshKey.PublicKey)]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// rememberAuthorized marks this key as already written to authorized keys..
|
// rememberAuthorized marks this key as already written to authorized keys..
|
||||||
func (s *SSHAccess) rememberAuthorized(sshKey ssh.SSHKey) {
|
func (s *SSHAccess) rememberAuthorized(sshKey UserKey) {
|
||||||
s.authorized[fmt.Sprintf("%s:%s", sshKey.Username, sshKey.KeyValue)] = true
|
s.authorized[fmt.Sprintf("%s:%s", sshKey.Username, sshKey.PublicKey)] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SSHAccess) DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.SSHKey) error {
|
func (s *SSHAccess) DeploySSHAuthorizedKey(ctx context.Context, sshKey UserKey) error {
|
||||||
// allow only one thread to write to authorized keys, create users and update the authorized map at a time
|
// allow only one thread to write to authorized keys, create users and update the authorized map at a time
|
||||||
s.mux.Lock()
|
s.mux.Lock()
|
||||||
defer s.mux.Unlock()
|
defer s.mux.Unlock()
|
||||||
@ -61,31 +58,31 @@ func (s *SSHAccess) DeploySSHAuthorizedKey(ctx context.Context, sshKey ssh.SSHKe
|
|||||||
// CoreOS uses https://github.com/coreos/ssh-key-dir to search for ssh keys in ~/.ssh/authorized_keys.d/*
|
// CoreOS uses https://github.com/coreos/ssh-key-dir to search for ssh keys in ~/.ssh/authorized_keys.d/*
|
||||||
sshFolder := fmt.Sprintf("%s/.ssh", user.Home)
|
sshFolder := fmt.Sprintf("%s/.ssh", user.Home)
|
||||||
authorized_keys_d := fmt.Sprintf("%s/authorized_keys.d", sshFolder)
|
authorized_keys_d := fmt.Sprintf("%s/authorized_keys.d", sshFolder)
|
||||||
if err := s.fs.MkdirAll(authorized_keys_d, 0o700); err != nil {
|
if err := s.userManager.Fs.MkdirAll(authorized_keys_d, 0o700); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.fs.Chown(sshFolder, user.Uid, user.Gid); err != nil {
|
if err := s.userManager.Fs.Chown(sshFolder, user.Uid, user.Gid); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.fs.Chown(authorized_keys_d, user.Uid, user.Gid); err != nil {
|
if err := s.userManager.Fs.Chown(authorized_keys_d, user.Uid, user.Gid); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
authorizedKeysPath := fmt.Sprintf("%s/debugd", authorized_keys_d)
|
authorizedKeysPath := fmt.Sprintf("%s/ssh-keys", authorized_keys_d)
|
||||||
authorizedKeysFile, err := s.fs.OpenFile(authorizedKeysPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
authorizedKeysFile, err := s.userManager.Fs.OpenFile(authorizedKeysPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = authorizedKeysFile.WriteString(fmt.Sprintf("%s %s\n", sshKey.KeyValue, sshKey.Username))
|
_, err = authorizedKeysFile.WriteString(fmt.Sprintf("%s %s\n", sshKey.PublicKey, sshKey.Username))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := authorizedKeysFile.Close(); err != nil {
|
if err := authorizedKeysFile.Close(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.fs.Chown(authorizedKeysPath, user.Uid, user.Gid); err != nil {
|
if err := s.userManager.Fs.Chown(authorizedKeysPath, user.Uid, user.Gid); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.fs.Chmod(authorizedKeysPath, 0o644); err != nil {
|
if err := s.userManager.Fs.Chmod(authorizedKeysPath, 0o644); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.rememberAuthorized(sshKey)
|
s.rememberAuthorized(sshKey)
|
@ -1,26 +1,24 @@
|
|||||||
package deploy
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/deploy/passwd"
|
"github.com/edgelesssys/constellation/internal/deploy/user"
|
||||||
"github.com/edgelesssys/constellation/debugd/ssh"
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDeploySSHAuthorizedKey(t *testing.T) {
|
func TestDeploySSHAuthorizedKey(t *testing.T) {
|
||||||
authorizedKey := ssh.SSHKey{
|
authorizedKey := UserKey{
|
||||||
Username: "user",
|
Username: "user",
|
||||||
KeyValue: "ssh-rsa testkey",
|
PublicKey: "ssh-rsa testkey",
|
||||||
}
|
}
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
fs afero.Fs
|
fs afero.Fs
|
||||||
userCreator *stubUserCreator
|
|
||||||
passwdContents string
|
passwdContents string
|
||||||
alreadyDeployed bool
|
alreadyDeployed bool
|
||||||
readonly bool
|
readonly bool
|
||||||
@ -30,40 +28,26 @@ func TestDeploySSHAuthorizedKey(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
"deploy works": {
|
"deploy works": {
|
||||||
fs: afero.NewMemMapFs(),
|
fs: afero.NewMemMapFs(),
|
||||||
userCreator: &stubUserCreator{},
|
|
||||||
passwdContents: "user:x:1000:1000:user:/home/user:/bin/bash\n",
|
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
wantFile: true,
|
wantFile: true,
|
||||||
wantFileContents: "ssh-rsa testkey user\n",
|
wantFileContents: "ssh-rsa testkey user\n",
|
||||||
},
|
},
|
||||||
"appending ssh key works": {
|
"appending ssh key works": {
|
||||||
fs: memMapFsWithFile("/home/user/.ssh/authorized_keys.d/debugd", "ssh-rsa preexistingkey user\n"),
|
fs: memMapFsWithFile("/home/user/.ssh/authorized_keys.d/ssh-keys", "ssh-rsa preexistingkey user\n"),
|
||||||
userCreator: &stubUserCreator{},
|
|
||||||
passwdContents: "user:x:1000:1000:user:/home/user:/bin/bash\n",
|
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
wantFile: true,
|
wantFile: true,
|
||||||
wantFileContents: "ssh-rsa preexistingkey user\nssh-rsa testkey user\n",
|
wantFileContents: "ssh-rsa preexistingkey user\nssh-rsa testkey user\n",
|
||||||
},
|
},
|
||||||
"redeployment avoided": {
|
"redeployment avoided": {
|
||||||
fs: afero.NewMemMapFs(),
|
fs: afero.NewMemMapFs(),
|
||||||
userCreator: &stubUserCreator{},
|
|
||||||
passwdContents: "user:x:1000:1000:user:/home/user:/bin/bash\n",
|
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
alreadyDeployed: true,
|
alreadyDeployed: true,
|
||||||
wantFile: false,
|
wantFile: false,
|
||||||
},
|
},
|
||||||
"user does not exist": {
|
|
||||||
fs: afero.NewMemMapFs(),
|
|
||||||
userCreator: &stubUserCreator{},
|
|
||||||
passwdContents: "",
|
|
||||||
wantErr: true,
|
|
||||||
},
|
|
||||||
"readonly fs": {
|
"readonly fs": {
|
||||||
fs: afero.NewMemMapFs(),
|
fs: afero.NewMemMapFs(),
|
||||||
userCreator: &stubUserCreator{},
|
readonly: true,
|
||||||
passwdContents: "user:x:1000:1000:user:/home/user:/bin/bash\n",
|
wantErr: true,
|
||||||
readonly: true,
|
|
||||||
wantErr: true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,24 +55,20 @@ func TestDeploySSHAuthorizedKey(t *testing.T) {
|
|||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
userManager := user.NewLinuxUserManagerFake(tc.fs)
|
||||||
|
|
||||||
assert.NoError(afero.WriteFile(tc.fs, "/etc/passwd", []byte(tc.passwdContents), 0o755))
|
assert.NoError(afero.WriteFile(userManager.Fs, "/etc/passwd", []byte(tc.passwdContents), 0o755))
|
||||||
if tc.readonly {
|
if tc.readonly {
|
||||||
tc.fs = afero.NewReadOnlyFs(tc.fs)
|
userManager.Fs = afero.NewReadOnlyFs(userManager.Fs)
|
||||||
}
|
}
|
||||||
authorized := map[string]bool{}
|
authorized := map[string]bool{}
|
||||||
if tc.alreadyDeployed {
|
if tc.alreadyDeployed {
|
||||||
authorized["user:ssh-rsa testkey"] = true
|
authorized["user:ssh-rsa testkey"] = true
|
||||||
}
|
}
|
||||||
sshAccess := SSHAccess{
|
sshAccess := SSHAccess{
|
||||||
fs: tc.fs,
|
userManager: userManager,
|
||||||
userManager: LinuxUserManager{
|
mux: sync.Mutex{},
|
||||||
fs: tc.fs,
|
authorized: authorized,
|
||||||
passwd: passwd.Passwd{},
|
|
||||||
creator: tc.userCreator,
|
|
||||||
},
|
|
||||||
mux: sync.Mutex{},
|
|
||||||
authorized: authorized,
|
|
||||||
}
|
}
|
||||||
err := sshAccess.DeploySSHAuthorizedKey(context.Background(), authorizedKey)
|
err := sshAccess.DeploySSHAuthorizedKey(context.Background(), authorizedKey)
|
||||||
|
|
||||||
@ -98,11 +78,11 @@ func TestDeploySSHAuthorizedKey(t *testing.T) {
|
|||||||
}
|
}
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
if tc.wantFile {
|
if tc.wantFile {
|
||||||
fileContents, err := afero.ReadFile(tc.fs, "/home/user/.ssh/authorized_keys.d/debugd")
|
fileContents, err := afero.ReadFile(userManager.Fs, "/home/user/.ssh/authorized_keys.d/ssh-keys")
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
assert.Equal(tc.wantFileContents, string(fileContents))
|
assert.Equal(tc.wantFileContents, string(fileContents))
|
||||||
} else {
|
} else {
|
||||||
exists, err := afero.Exists(tc.fs, "/home/user/.ssh/authorized_keys.d/debugd")
|
exists, err := afero.Exists(userManager.Fs, "/home/user/.ssh/authorized_keys.d/ssh-keys")
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
assert.False(exists)
|
assert.False(exists)
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package createuser
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
147
internal/deploy/user/linux_user.go
Normal file
147
internal/deploy/user/linux_user.go
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrUserDoesNotExist is returned by GetLinuxUser if a linux user does not exist yet.
|
||||||
|
var ErrUserDoesNotExist = errors.New("user does not exist")
|
||||||
|
|
||||||
|
type passwdParser interface {
|
||||||
|
Parse(fs afero.Fs) (Entries, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type userCreator interface {
|
||||||
|
CreateUser(ctx context.Context, username string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinuxUser holds relevant information about a linux user (subset of /etc/passwd).
|
||||||
|
type LinuxUser struct {
|
||||||
|
Username string
|
||||||
|
Home string
|
||||||
|
Uid int
|
||||||
|
Gid int
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinuxUserManager can retrieve information on linux users and create new users.
|
||||||
|
type LinuxUserManager struct {
|
||||||
|
Fs afero.Fs
|
||||||
|
Passwd passwdParser
|
||||||
|
Creator userCreator
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLinuxUserManager creates a new LinuxUserManager.
|
||||||
|
func NewLinuxUserManager(fs afero.Fs) LinuxUserManager {
|
||||||
|
return LinuxUserManager{
|
||||||
|
Fs: fs,
|
||||||
|
Passwd: Passwd{},
|
||||||
|
Creator: Unix{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLinuxUserManagerFake creates a new LinuxUserManager that is used for unit tests.
|
||||||
|
func NewLinuxUserManagerFake(fs afero.Fs) LinuxUserManager {
|
||||||
|
return LinuxUserManager{
|
||||||
|
Fs: fs,
|
||||||
|
Passwd: Passwd{},
|
||||||
|
Creator: &StubUserCreator{fs: fs},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StubUserCreator is used for unit tests.
|
||||||
|
type StubUserCreator struct {
|
||||||
|
fs afero.Fs
|
||||||
|
usernames []string
|
||||||
|
createUserErr error
|
||||||
|
currentUID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *StubUserCreator) CreateUser(ctx context.Context, username string) error {
|
||||||
|
if stringInSlice(username, s.usernames) {
|
||||||
|
return errors.New("username already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want created users to start at UID 1000
|
||||||
|
if s.currentUID == 0 {
|
||||||
|
s.currentUID = 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.createUserErr != nil {
|
||||||
|
return s.createUserErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no predefined error is supposed to happen, increase the UID (unless the file system code fails)
|
||||||
|
if s.fs != nil {
|
||||||
|
lineToWrite := fmt.Sprintf("%s:x:%d:%d:%s:/home/%s:/bin/bash\n", username, s.currentUID, s.currentUID, username, username)
|
||||||
|
file, err := s.fs.OpenFile("/etc/passwd", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
n, err := file.WriteString(lineToWrite)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if n != len(lineToWrite) {
|
||||||
|
return errors.New("written text too short")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.currentUID += 1
|
||||||
|
s.usernames = append(s.usernames, username)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getLinuxUser tries to find an existing linux user in /etc/passwd.
|
||||||
|
func (l *LinuxUserManager) getLinuxUser(username string) (LinuxUser, error) {
|
||||||
|
entries, err := l.Passwd.Parse(l.Fs)
|
||||||
|
if err != nil {
|
||||||
|
return LinuxUser{}, err
|
||||||
|
}
|
||||||
|
if _, ok := entries[username]; !ok {
|
||||||
|
return LinuxUser{}, ErrUserDoesNotExist
|
||||||
|
}
|
||||||
|
entry := entries[username]
|
||||||
|
uid, err := strconv.Atoi(entry.Uid)
|
||||||
|
if err != nil {
|
||||||
|
return LinuxUser{}, fmt.Errorf("failed to parse users uid: %w", err)
|
||||||
|
}
|
||||||
|
gid, err := strconv.Atoi(entry.Gid)
|
||||||
|
if err != nil {
|
||||||
|
return LinuxUser{}, fmt.Errorf("failed to parse users gid: %w", err)
|
||||||
|
}
|
||||||
|
return LinuxUser{
|
||||||
|
Username: username,
|
||||||
|
Home: entry.Home,
|
||||||
|
Uid: uid,
|
||||||
|
Gid: gid,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnsureLinuxUserExists will try to create the user specified by username and call GetLinuxUser to retrieve user information.
|
||||||
|
func (l *LinuxUserManager) EnsureLinuxUserExists(ctx context.Context, username string) (LinuxUser, error) {
|
||||||
|
// try to create user (even if it already exists)
|
||||||
|
if err := l.Creator.CreateUser(ctx, username); err != nil {
|
||||||
|
return LinuxUser{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.getLinuxUser(username)
|
||||||
|
}
|
||||||
|
|
||||||
|
// stringInSlice checks if a given string exists in a slice of strings.
|
||||||
|
func stringInSlice(a string, list []string) bool {
|
||||||
|
for _, b := range list {
|
||||||
|
if b == a {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
package deploy
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/debugd/debugd/deploy/passwd"
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -15,13 +14,11 @@ func TestGetLinuxUser(t *testing.T) {
|
|||||||
username := "user"
|
username := "user"
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
userCreator *stubUserCreator
|
|
||||||
passwdContents string
|
passwdContents string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
wantUser LinuxUser
|
wantUser LinuxUser
|
||||||
}{
|
}{
|
||||||
"get works": {
|
"get works": {
|
||||||
userCreator: &stubUserCreator{},
|
|
||||||
passwdContents: "user:x:1000:1000:user:/home/user:/bin/bash\n",
|
passwdContents: "user:x:1000:1000:user:/home/user:/bin/bash\n",
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
wantUser: LinuxUser{
|
wantUser: LinuxUser{
|
||||||
@ -32,22 +29,18 @@ func TestGetLinuxUser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"user does not exist": {
|
"user does not exist": {
|
||||||
userCreator: &stubUserCreator{},
|
|
||||||
passwdContents: "",
|
passwdContents: "",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"parse fails": {
|
"parse fails": {
|
||||||
userCreator: &stubUserCreator{},
|
|
||||||
passwdContents: "invalid contents\n",
|
passwdContents: "invalid contents\n",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"invalid uid": {
|
"invalid uid": {
|
||||||
userCreator: &stubUserCreator{},
|
|
||||||
passwdContents: "user:x:invalid:1000:user:/home/user:/bin/bash\n",
|
passwdContents: "user:x:invalid:1000:user:/home/user:/bin/bash\n",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"invalid gid": {
|
"invalid gid": {
|
||||||
userCreator: &stubUserCreator{},
|
|
||||||
passwdContents: "user:x:1000:invalid:user:/home/user:/bin/bash\n",
|
passwdContents: "user:x:1000:invalid:user:/home/user:/bin/bash\n",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@ -60,11 +53,7 @@ func TestGetLinuxUser(t *testing.T) {
|
|||||||
|
|
||||||
fs := afero.NewMemMapFs()
|
fs := afero.NewMemMapFs()
|
||||||
assert.NoError(afero.WriteFile(fs, "/etc/passwd", []byte(tc.passwdContents), 0o755))
|
assert.NoError(afero.WriteFile(fs, "/etc/passwd", []byte(tc.passwdContents), 0o755))
|
||||||
manager := LinuxUserManager{
|
manager := NewLinuxUserManagerFake(fs)
|
||||||
fs: fs,
|
|
||||||
passwd: passwd.Passwd{},
|
|
||||||
creator: tc.userCreator,
|
|
||||||
}
|
|
||||||
user, err := manager.getLinuxUser(username)
|
user, err := manager.getLinuxUser(username)
|
||||||
|
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
@ -81,15 +70,13 @@ func TestEnsureLinuxUserExists(t *testing.T) {
|
|||||||
username := "user"
|
username := "user"
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
userCreator *stubUserCreator
|
userCreator *StubUserCreator
|
||||||
passwdContents string
|
wantErr bool
|
||||||
wantErr bool
|
wantUser LinuxUser
|
||||||
wantUser LinuxUser
|
|
||||||
}{
|
}{
|
||||||
"create works": {
|
"create works": {
|
||||||
userCreator: &stubUserCreator{},
|
userCreator: &StubUserCreator{},
|
||||||
passwdContents: "user:x:1000:1000:user:/home/user:/bin/bash\n",
|
wantErr: false,
|
||||||
wantErr: false,
|
|
||||||
wantUser: LinuxUser{
|
wantUser: LinuxUser{
|
||||||
Username: "user",
|
Username: "user",
|
||||||
Home: "/home/user",
|
Home: "/home/user",
|
||||||
@ -98,11 +85,10 @@ func TestEnsureLinuxUserExists(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"create fails": {
|
"create fails": {
|
||||||
userCreator: &stubUserCreator{
|
userCreator: &StubUserCreator{
|
||||||
createUserErr: errors.New("create fails"),
|
createUserErr: errors.New("create fails"),
|
||||||
},
|
},
|
||||||
passwdContents: "user:x:1000:1000:user:/home/user:/bin/bash\n",
|
wantErr: true,
|
||||||
wantErr: true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,12 +98,9 @@ func TestEnsureLinuxUserExists(t *testing.T) {
|
|||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
fs := afero.NewMemMapFs()
|
fs := afero.NewMemMapFs()
|
||||||
assert.NoError(afero.WriteFile(fs, "/etc/passwd", []byte(tc.passwdContents), 0o755))
|
manager := NewLinuxUserManagerFake(fs)
|
||||||
manager := LinuxUserManager{
|
tc.userCreator.fs = fs
|
||||||
fs: fs,
|
manager.Creator = tc.userCreator
|
||||||
passwd: passwd.Passwd{},
|
|
||||||
creator: tc.userCreator,
|
|
||||||
}
|
|
||||||
user, err := manager.EnsureLinuxUserExists(context.Background(), username)
|
user, err := manager.EnsureLinuxUserExists(context.Background(), username)
|
||||||
|
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
@ -131,12 +114,10 @@ func TestEnsureLinuxUserExists(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type stubUserCreator struct {
|
func TestStringInSlice(t *testing.T) {
|
||||||
usernames []string
|
assert := assert.New(t)
|
||||||
createUserErr error
|
testSlice := []string{"abc", "efg", "xyz"}
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stubUserCreator) CreateUser(ctx context.Context, username string) error {
|
assert.True(stringInSlice("efg", testSlice))
|
||||||
s.usernames = append(s.usernames, username)
|
assert.False(stringInSlice("hij", testSlice))
|
||||||
return s.createUserErr
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package passwd
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
@ -1,4 +1,4 @@
|
|||||||
package passwd
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
@ -9,10 +9,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
||||||
"github.com/edgelesssys/constellation/coordinator/config"
|
"github.com/edgelesssys/constellation/coordinator/config"
|
||||||
"github.com/edgelesssys/constellation/coordinator/nodestate"
|
"github.com/edgelesssys/constellation/coordinator/nodestate"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/cli/file"
|
|
||||||
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
"github.com/edgelesssys/constellation/coordinator/attestation/vtpm"
|
||||||
"github.com/edgelesssys/constellation/coordinator/config"
|
"github.com/edgelesssys/constellation/coordinator/config"
|
||||||
"github.com/edgelesssys/constellation/coordinator/nodestate"
|
"github.com/edgelesssys/constellation/coordinator/nodestate"
|
||||||
|
"github.com/edgelesssys/constellation/internal/file"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user