2023-06-23 13:12:18 +00:00
package modules
import (
"context"
"fmt"
"os"
"strings"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/authmate"
2023-11-16 11:39:58 +00:00
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/frostfsid"
2023-06-23 13:12:18 +00:00
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/wallet"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var updateSecretCmd = & cobra . Command {
Use : "update-secret" ,
Short : "Update a secret in FrostFS network" ,
Long : ` Creates new access box that will be available for extend list of s3 gates , preserve all timeout from initial credentials .
After using this command you can use initial access - key - id to interact with newly added gates ` ,
Example : ` To extend list of s3 gates that can use existing credentials run :
frostfs - s3 - authmate update - secret -- wallet wallet . json -- peer s01 . neofs . devenv : 8080 -- gate - wallet s3 - wallet . json \
-- gate - public - key 031 a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a \
-- gate - public - key 021 dc56fc6d81d581ae7605a8e00e0e0bab6cbad566a924a527339475a97a8e38e \
-- acces - key - id EC3tyWpTEKfGNS888PFBpwQzZTrnwDXReGjgAxa8Em1h037VoWktUZCAk1LVA5SvVbVd2NHHb2NQm9jhcd5WFU5VD ` ,
RunE : runUpdateSecretCmd ,
}
func initUpdateSecretCmd ( ) {
updateSecretCmd . Flags ( ) . String ( walletFlag , "" , "Path to the wallet that will be owner of the credentials" )
updateSecretCmd . Flags ( ) . String ( addressFlag , "" , "Address of the wallet account" )
updateSecretCmd . Flags ( ) . String ( peerFlag , "" , "Address of a frostfs peer to connect to" )
updateSecretCmd . Flags ( ) . String ( gateWalletFlag , "" , "Path to the s3 gateway wallet to decrypt accessbox" )
updateSecretCmd . Flags ( ) . String ( gateAddressFlag , "" , "Address of the s3 gateway wallet account" )
updateSecretCmd . Flags ( ) . String ( accessKeyIDFlag , "" , "Access key id of s3 credential for which secret must be obtained" )
updateSecretCmd . Flags ( ) . StringSlice ( gatePublicKeyFlag , nil , "Public 256r1 key of a gate (use flags repeatedly for multiple gates or separate them by comma)" )
updateSecretCmd . Flags ( ) . Duration ( poolDialTimeoutFlag , defaultPoolDialTimeout , "Timeout for connection to the node in pool to be established" )
updateSecretCmd . Flags ( ) . Duration ( poolHealthcheckTimeoutFlag , defaultPoolHealthcheckTimeout , "Timeout for request to node to decide if it is alive" )
updateSecretCmd . Flags ( ) . Duration ( poolRebalanceIntervalFlag , defaultPoolRebalanceInterval , "Interval for updating nodes health status" )
updateSecretCmd . Flags ( ) . Duration ( poolStreamTimeoutFlag , defaultPoolStreamTimeout , "Timeout for individual operation in streaming RPC" )
2023-11-16 11:39:58 +00:00
updateSecretCmd . Flags ( ) . String ( frostfsIDFlag , "" , "FrostfsID contract hash (LE) or name in NNS to register public key in contract (rpc-endpoint flag also must be provided)" )
2023-12-21 14:34:46 +00:00
updateSecretCmd . Flags ( ) . String ( frostfsIDProxyFlag , "" , "Proxy contract hash (LE) or name in NNS to use when interact with frostfsid contract" )
updateSecretCmd . Flags ( ) . String ( frostfsIDNamespaceFlag , "" , "Namespace to register public key in frostfsid contract" )
2023-11-16 11:39:58 +00:00
updateSecretCmd . Flags ( ) . String ( rpcEndpointFlag , "" , "NEO node RPC address" )
2023-06-23 13:12:18 +00:00
_ = updateSecretCmd . MarkFlagRequired ( walletFlag )
_ = updateSecretCmd . MarkFlagRequired ( peerFlag )
_ = updateSecretCmd . MarkFlagRequired ( gateWalletFlag )
_ = updateSecretCmd . MarkFlagRequired ( accessKeyIDFlag )
_ = updateSecretCmd . MarkFlagRequired ( gatePublicKeyFlag )
}
func runUpdateSecretCmd ( cmd * cobra . Command , _ [ ] string ) error {
ctx , cancel := context . WithTimeout ( cmd . Context ( ) , viper . GetDuration ( timeoutFlag ) )
defer cancel ( )
log := getLogger ( )
password := wallet . GetPassword ( viper . GetViper ( ) , walletPassphraseCfg )
key , err := wallet . GetKeyFromPath ( viper . GetString ( walletFlag ) , viper . GetString ( addressFlag ) , password )
if err != nil {
2023-09-04 18:01:56 +00:00
return wrapPreparationError ( fmt . Errorf ( "failed to load frostfs private key: %s" , err ) )
2023-06-23 13:12:18 +00:00
}
gatePassword := wallet . GetPassword ( viper . GetViper ( ) , walletGatePassphraseCfg )
gateKey , err := wallet . GetKeyFromPath ( viper . GetString ( gateWalletFlag ) , viper . GetString ( gateAddressFlag ) , gatePassword )
if err != nil {
2023-09-04 18:01:56 +00:00
return wrapPreparationError ( fmt . Errorf ( "failed to load s3 gate private key: %s" , err ) )
2023-06-23 13:12:18 +00:00
}
var accessBoxAddress oid . Address
credAddr := strings . Replace ( viper . GetString ( accessKeyIDFlag ) , "0" , "/" , 1 )
if err = accessBoxAddress . DecodeString ( credAddr ) ; err != nil {
2023-09-04 18:01:56 +00:00
return wrapPreparationError ( fmt . Errorf ( "failed to parse creds address: %w" , err ) )
2023-06-23 13:12:18 +00:00
}
var gatesPublicKeys [ ] * keys . PublicKey
for _ , keyStr := range viper . GetStringSlice ( gatePublicKeyFlag ) {
gpk , err := keys . NewPublicKeyFromString ( keyStr )
if err != nil {
2023-09-04 18:01:56 +00:00
return wrapPreparationError ( fmt . Errorf ( "failed to load gate's public key: %s" , err ) )
2023-06-23 13:12:18 +00:00
}
gatesPublicKeys = append ( gatesPublicKeys , gpk )
}
poolCfg := PoolConfig {
2023-08-03 12:08:22 +00:00
Key : key ,
2023-06-23 13:12:18 +00:00
Address : viper . GetString ( peerFlag ) ,
DialTimeout : viper . GetDuration ( poolDialTimeoutFlag ) ,
HealthcheckTimeout : viper . GetDuration ( poolHealthcheckTimeoutFlag ) ,
StreamTimeout : viper . GetDuration ( poolStreamTimeoutFlag ) ,
RebalanceInterval : viper . GetDuration ( poolRebalanceIntervalFlag ) ,
}
frostFS , err := createFrostFS ( ctx , log , poolCfg )
if err != nil {
2023-09-04 18:01:56 +00:00
return wrapFrostFSInitError ( fmt . Errorf ( "failed to create FrostFS component: %s" , err ) )
2023-06-23 13:12:18 +00:00
}
2023-11-16 11:39:58 +00:00
frostFSID := viper . GetString ( frostfsIDFlag )
if frostFSID != "" {
rpcAddress := viper . GetString ( rpcEndpointFlag )
if rpcAddress == "" {
return wrapPreparationError ( fmt . Errorf ( "you can use '%s' flag only along with '%s'" , frostfsIDFlag , rpcEndpointFlag ) )
}
cfg := frostfsid . Config {
2023-12-21 14:34:46 +00:00
RPCAddress : rpcAddress ,
Contract : frostFSID ,
ProxyContract : viper . GetString ( frostfsIDProxyFlag ) ,
Key : key ,
2023-11-16 11:39:58 +00:00
}
frostfsIDClient , err := createFrostFSID ( ctx , log , cfg )
if err != nil {
return wrapFrostFSIDInitError ( err )
}
2023-12-21 14:34:46 +00:00
if err = frostfsIDClient . RegisterPublicKey ( viper . GetString ( frostfsIDNamespaceFlag ) , key . PublicKey ( ) ) ; err != nil {
2023-11-16 11:39:58 +00:00
return wrapBusinessLogicError ( fmt . Errorf ( "failed to register key in frostfsid: %w" , err ) )
}
}
2023-06-23 13:12:18 +00:00
updateSecretOptions := & authmate . UpdateSecretOptions {
Address : accessBoxAddress ,
FrostFSKey : key ,
GatesPublicKeys : gatesPublicKeys ,
GatePrivateKey : gateKey ,
}
if err = authmate . New ( log , frostFS ) . UpdateSecret ( ctx , os . Stdout , updateSecretOptions ) ; err != nil {
2023-09-04 18:01:56 +00:00
return wrapBusinessLogicError ( fmt . Errorf ( "failed to update secret: %s" , err ) )
2023-06-23 13:12:18 +00:00
}
return nil
}