Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions cmd/rofl/machine/mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,10 @@ var (
}

changeAdminCmd = &cobra.Command{
Use: "change-admin [<machine-name> | <provider-address>:<machine-id>] <new-admin>",
Short: "Change the machine administrator",
Args: cobra.RangeArgs(1, 2),
Use: "set-admin [<machine-name> | <provider-address>:<machine-id>] <new-admin>",
Short: "Change the machine administrator",
Aliases: []string{"change-admin"},
Args: cobra.RangeArgs(1, 2),
Run: func(_ *cobra.Command, args []string) {
txCfg := common.GetTransactionConfig()
mCfg, err := resolveMachineCfg(args, &roflCommon.ManifestOptions{
Expand Down
1 change: 1 addition & 0 deletions cmd/rofl/rofl.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func init() {
Cmd.AddCommand(identityCmd)
Cmd.AddCommand(secretCmd)
Cmd.AddCommand(upgradeCmd)
Cmd.AddCommand(setAdminCmd)
Cmd.AddCommand(provider.Cmd)
Cmd.AddCommand(machine.Cmd)
}
107 changes: 107 additions & 0 deletions cmd/rofl/set_admin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package rofl

import (
"context"
"fmt"

"github.com/spf13/cobra"

"github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/rofl"

buildRofl "github.com/oasisprotocol/cli/build/rofl"
"github.com/oasisprotocol/cli/cmd/common"
roflCommon "github.com/oasisprotocol/cli/cmd/rofl/common"
cliConfig "github.com/oasisprotocol/cli/config"
)

var setAdminCmd = &cobra.Command{
Use: "set-admin <new-admin>",
Short: "Change the administrator of the application in ROFL",
Aliases: []string{"change-admin"},
Args: cobra.ExactArgs(1),
Run: func(_ *cobra.Command, args []string) {
txCfg := common.GetTransactionConfig()

manifest, deployment, npa := roflCommon.LoadManifestAndSetNPA(&roflCommon.ManifestOptions{
NeedAppID: true,
NeedAdmin: true,
})

var appID rofl.AppID
if err := appID.UnmarshalText([]byte(deployment.AppID)); err != nil {
cobra.CheckErr(fmt.Errorf("malformed ROFL app ID: %w", err))
}

npa.MustHaveAccount()
npa.MustHaveParaTime()

if deployment.Policy == nil {
cobra.CheckErr("no policy configured in the manifest")
}

oldAdminAddr, _, err := common.ResolveLocalAccountOrAddress(npa.Network, deployment.Admin)
if err != nil {
cobra.CheckErr(fmt.Errorf("bad current administrator address: %w", err))
}

newAdminAddr, newAdminEthAddr, err := common.ResolveLocalAccountOrAddress(npa.Network, args[0])
if err != nil {
cobra.CheckErr(fmt.Errorf("invalid new admin address: %w", err))
}

if *oldAdminAddr == *newAdminAddr {
fmt.Println("New admin is the same as the current admin, nothing to do.")
return
}

// When not in offline mode, connect to the given network endpoint.
ctx := context.Background()
var conn connection.Connection
if !txCfg.Offline {
conn, err = connection.Connect(ctx, npa.Network)
cobra.CheckErr(err)
}

newAdminStr := newAdminAddr.String()
if newAdminEthAddr != nil {
newAdminStr = newAdminEthAddr.Hex()
}

fmt.Printf("App ID: %s\n", deployment.AppID)
fmt.Printf("Old admin: %s\n", common.PrettyAddress(oldAdminAddr.String()))
fmt.Printf("New admin: %s\n", common.PrettyAddress(newAdminStr))

secrets := buildRofl.PrepareSecrets(deployment.Secrets)

tx := rofl.NewUpdateTx(nil, &rofl.Update{
ID: appID,
Policy: *deployment.Policy.AsDescriptor(),
Admin: newAdminAddr,
Metadata: manifest.GetMetadata(roflCommon.DeploymentName),
Secrets: secrets,
})

acc := common.LoadAccount(cliConfig.Global(), npa.AccountName)
sigTx, meta, err := common.SignParaTimeTransaction(ctx, npa, acc, conn, tx, nil)
cobra.CheckErr(err)

if !common.BroadcastOrExportTransaction(ctx, npa, conn, sigTx, meta, nil) {
return
}

// Transaction succeeded — update the manifest with the new admin.
deployment.Admin = args[0]
if err = manifest.Save(); err != nil {
cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err))
}

fmt.Printf("ROFL admin changed to %s.\n", common.PrettyAddress(newAdminStr))
},
}

func init() {
common.AddAccountFlag(setAdminCmd)
setAdminCmd.Flags().AddFlagSet(common.RuntimeTxFlags)
setAdminCmd.Flags().AddFlagSet(roflCommon.DeploymentFlags)
}
27 changes: 27 additions & 0 deletions docs/rofl.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,33 @@ their latest versions. This includes:

![code shell](../examples/rofl/upgrade.in.static)

### Change ROFL app administrator {#set-admin}

Run `rofl set-admin` to transfer ownership of a ROFL app to a new
administrator. The transaction is signed by the current admin and, on success,
the manifest is updated with the new admin.

![code shell](../examples/rofl/set-admin.in.static)

### Change ROFL machine administrator {#machine-set-admin}

Run `rofl machine set-admin` to change the administrator of an individual
machine instance.

![code shell](../examples/rofl/machine-set-admin.in.static)

:::info ROFL admin vs machine admin

The **ROFL admin** (changed via `oasis rofl set-admin`) owns the
application — transfer ownership, upgrades, policy changes, removal.

The **machine admin** (changed via `oasis rofl machine set-admin`) manages
an individual machine instance — execution, restarts, stops.

These are independent roles.

:::

### Remove ROFL app from the network {#remove}

Run `rofl remove` to deregister your ROFL app:
Expand Down
1 change: 1 addition & 0 deletions examples/rofl/machine-set-admin.in.static
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
oasis rofl machine set-admin [<machine-name> | <provider-address>:<machine-id>] <new-admin>
1 change: 1 addition & 0 deletions examples/rofl/set-admin.in.static
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
oasis rofl set-admin <new-admin>
Loading