Using the RBAC Do-As Delegation Feature

Overview

This example shows you how to create a simple policy to enable a user to perform actions as another user. Take a look here for an overview of Fugue’s RBAC feature, or here for an overview of the policy command. This example uses very similar infrastructure to what is demonstrated in the Using the RBAC Feature, with one major difference, the --do-as flag.

In this example you will be creating a policy, running a composition, using the policy you created to test a policy rule that allows you to delegate permissions to issue commands as another user.

Prerequisites

You’ll need to have the Fugue CLI set up and the Conductor installed before you can run this example. If you haven’t done so yet, it just takes a few quick steps.

You’ll also need to be running the paid version of Fugue, not Free Fugue, since the paid version offers the full RBAC feature.

What We’ll Do In This Example

We’ll quickly review the basics and then cover how to write Ludwig to make a rule in an RBAC policy to delegate authority from one user to another. We’ll also apply the policy, switch users, run a composition, suspend a composition as another user by using the --do-as flag, and finally switch users again to kill the composition.

What We’ll Have When We’re Done

We’ll be using the HelloWorld.lw composition from Hello World, Part 2: Fugue Basics to issue commands with the --do-as flag.

How Long It Will Take

About 25 minutes.

Download

You can download the source code for this example from Github:

If you executed init during the Quick Setup, download the compositions to the directory where you ran the command.

Get editor plug-ins here.

Let’s Go!

Writing the Policy Composition

First, we need to write the RBAC policy composition. A policy consists of rules that permit users to execute specific Fugue commands on specific accounts.

We’ll start with the composition keyword. We’ll also import the Fugue.System.Policy library.

composition

import Fugue.System.Policy as Policy

Declaring the Account

This top-level binding tells the Conductor that the account named fugue should be known within the policy as the default account. The NamedAccount constructor allows you to refer to a Fugue-managed account by its name rather than its account ID. If you execute fugue account list, you can find the names of all Fugue-managed accounts, including the default fugue account.

default: Policy.NamedAccount {accountName: "fugue"}

Note: To refer to the account by its account ID use Account instead of NamedAccount and accountId instead of accountName.

Declaring Users

Now, we need to create a user called alice, and a user called bob in a top-level binding.

alice: Policy.User {userId: "alice"}
bob: Policy.User {userId: "bob"}

Declaring Rules

A rule is the keystone type of the Fugue RBAC system. Rules are made up of principals, actions, and subjects. A principal is an entity that can be authorized to perform an operation, like a user. An action is an operation a principal can perform, like a Fugue command. A subject is the target of the action, like an account or a process.

Access for non-root users is implicitly denied; in other words, a user cannot take an action unless it is explicitly written in a rule inside an attached policy.

For more details on creating rules take a look at How to Use RBAC, or an example on Using the RBAC Feature.

In the example below we’re declaring five rules for alice enabling her to run, kill, view status, suspend, and resume for a process.

aliceLimitedAccessDefault: Policy.accountRules {
  principals: [alice],
  accounts: [default],
  actions:[
    Policy.AccountRunProcess,
    Policy.AccountKillProcess,
    Policy.AccountStatusProcess,
    Policy.AccountSuspendProcess,
    Policy.AccountResumeProcess
  ]
}

We are going to repeat to create a function for bob. His actions are limited to a rule allowing him to check the status of a process, so we’ve named it bobCanViewStatus. All of the same syntax applies, and it looks like this:

bobCanViewStatus: Policy.accountRules {
  principals: [bob],
  accounts: [default],
  actions:[
    Policy.AccountStatusProcess
  ]
}

The final step for this example is to include a rule that defines delegation. We’ve named this rule bobCanActasAlice to make it clear what the rule is intended to do. The principal here is bob. The subject is Policy.PrincipalType(alice) to specify whose permissions bob can take on. The action is Policy.DelegationAction(RbacDoAs) to enable bob with permission to act as alice.

bobCanActasAlice: Policy.Rule {
   principal: bob,
   subject: Policy.PrincipalType(alice),
   action: Policy.DelegationAction(Policy.RbacDoAs),
}

Applying the Policy

Now that we’ve written our policy, we need to apply it by attaching it to the Conductor. The Conductor will create the new users, and then we’ll enable them by generating a secret for each.

We can apply the policy by running this command:

fugue policy rbac-attach Policy_DoAs.lw

We’ll see output like this:

Compiling Ludwig file Policy.lw ...
[ OK ] Successfully compiled. No errors.

Uploading policy to S3 ...
[ OK ] Successfully uploaded.

Requesting the Conductor set new policy ...
[ DONE ] Policy uploaded and applied.

This means that the Conductor has successfully compiled the policy composition, uploaded it to S3, and applied the policy. That also means that now there’s two new users, alice and bob.

Note: If you see an error about exceeding the max user limit, make sure you’re running the paid version of Fugue, not Free Fugue, and reach out to support@fugue.co.

We can prove both alice and bob exist by executing the fugue policy list-users command:

fugue policy list-users

The CLI will output a table like this one:

Fugue User list for main-user/xxxxxxxxxxxx - Fri May 4 2018 2:54pm

User Name    Enabled    Created    Updated
-----------  ---------  ---------  ---------
root         yes        11:42am    11:42am
alice        no         2:54pm     2:54pm
bob          no         2:54pm     2:54pm

[ HELP ] To enable a user, run "fugue policy generate-secret <user_id>"

There’s alice, bob, and another user – root. The root user is enabled by default, and it’s the one you’re using right now. The root user has access to all actions and all subjects.

Enabling The New Users

As you can see, neither alice nor bob is enabled yet, and the CLI has helpfully informed us how to enable a user: We need to generate a secret, or access token, to authenticate the user. So, let’s get to it:

fugue policy generate-secret alice

The CLI returns the generated user secret and a success message.

[ fugue policy ] Requesting the Conductor generate a secret for: alice ...

====================
User Credential Details:

[alice]
user = alice
secret = X6NAp++VOvs++aTPBR727+Ra9KIyu9ZaPb9jmdC+yZA=

[ HELP ] You can copy/paste these values into your credentials file /Users/main-user/credentials

Copy this information somewhere safe! (Hint: credstash works great for this.) Your user secret should be...well, secret.

And let’s do the same for bob:

fugue policy generate-secret bob

The CLI returns the generated user secret and a success message.

[ fugue policy ] Requesting the Conductor generate a secret for: bob ...

====================
User Credential Details:

[bob]
user = bob
secret = M5nuFi6jRHCD3efqN2YAEjBbz2Ajsi/JqrvcAmKdDLE=

[ HELP ] You can copy/paste these values into your credentials file /Users/main-user/credentials
====================
[ DONE ] Secret successfully generated.

Make sure to copy these credentials for bob as well.

Backing Up Root Credentials

This part is pretty important. If you open the credentials file, which was created when you ran fugue install, you’ll see a section that looks like this:

[default-xxxxxxxxxx-us-east-1]
user = root
secret = gIowKW6AnAM4fgBqEXAMPLEEXAMPLEEXAMPLEEXAMPLE=

These are your root credentials.

Warning

Do not lose your root credentials. They cannot be replaced with the policy generate-secret command. If you have lost your root credentials, see the reset-secret command or contact support@fugue.co.

Now would be an excellent time to back up your root creds somewhere safe. We’re going to need them again later when we switch back to root.

If you run fugue policy list-users again, you’ll see that alice and bob are enabled.

Fugue User list for main-user/xxxxxxxxxxxx - Fri May 4 2018 3:00pm

User Name    Enabled    Created    Updated
-----------  ---------  ---------  ---------
root         yes        11:42am    11:42am
alice        yes        2:54pm     2:57pm
bob          yes        2:54pm     2:58pm

Switching to the New User alice

To switch to the alice user, we’ll use the user set <user_id> <user_secret> command:

fugue user set alice X6NAp++VOvs++aTPBR727+Ra9KIyu9ZaPb9jmdC+yZA=

Only one user can be active at a time, so you’ll see a warning about overwriting your root credentials, and the CLI will prompt you for confirmation.

[ INFO ] This operation will overwrite profile 'default' in /Users/main-user/credentials

[ WARN ] Are you sure you want to proceed? [y/N]: y

Go ahead and hit yif you already backed up your root credentials somewhere!

The CLI will overwrite the existing file and create a new credentials file.

[ DONE ] The user has been set to 'alice'

Running a Composition

Now that we’re using Fugue as alice, we’re going to run the HelloWorld.lw composition. This simple composition creates a VPC and tags in your AWS account and will enable us to test out commands as both alice and bob.

fugue run HelloWorld.lw -a HelloWorld

The CLI will return output like this:

[ fugue run ] Running HelloWorld.lw

Run Details:
    Account: default
    Alias: HelloWorld

Compiling Ludwig file /Users/main-user/HelloWorld.lw
[ OK ] Successfully compiled. No errors.


Uploading compiled Ludwig composition to S3...
[ OK ] Successfully uploaded.

Requesting the Conductor to create and run process based on composition ...
[ DONE ] Process created and running.

State    Updated    Created    Account              FID                                   Alias       Flags      Last Message  Next Command
-------  ---------  ---------  -------------------  ------------------------------------  ----------  -------  --------------  --------------
Running  3:09pm     3:09pm     fugue-1525448721154  c8035e40-fc16-466d-ade2-42ac346bc269  HelloWorld  -e                       run

[ HELP ] Run the "fugue status" command to view details and status for all Fugue processes.

As you can see, alice ran the composition in the default account. This action is permitted via the aliceLimitedAccessDefault rule.

Testing Permissions for bob

Let’s switch to our other user, bob and see if he’s able to view the status of this process as defined in our policy.

$ fugue user set bob M5nuFi6jRHCD3efqN2YAEjBbz2Ajsi/JqrvcAmKdDLE=

Confirm that you want to have bob as the user with y, and you will see the following.

[ INFO ] This operation will overwrite profile 'default' in /Users/main-user/credentials

[ WARN ] Are you sure you want to proceed? [y/N]: y

[ DONE ] The user has been set to 'bob'

Now, as bob if you issue a fugue status you should see the process we launched as alice.

$ fugue status

Fugue Status Report for main-user/xxxxxxxxxxx - Fri May 4 2018 3:44pm

State    Updated    Created    Account    FID/Alias    Flags    Last Message
-------  ---------  ---------  ---------  -----------  -------  --------------
Running  3:09pm     3:09pm     fugue      HelloWorld   -e       SUCCEEDED

Now if bob attempts any other commands, for example suspend, the policy will prevent him from issuing commands for any actions that have not been explicitly defined.

$ fugue suspend HelloWorld
[ fugue suspend ] Suspending process with alias: HelloWorld

[ WARN ] Are you sure you want to suspend the process with alias: HelloWorld ? [y/N]: y

Requesting the Conductor to suspend process ...
[ ERROR ] Due to an attached RBAC policy, command 'suspend' is not allowed for user 'bob' on process [c8035e40-fc16-466d-ade2-42ac346bc269].

Perfect, this is exactly what we expected. Now, because our policy includes delegation for bob to act as alice, let’s try to issue that same command with the --do-as flag.

$ fugue --do-as alice suspend HelloWorld
[ fugue suspend ] Suspending process with alias: HelloWorld

[ WARN ] Are you sure you want to suspend the process with alias: HelloWorld ? [y/N]: y

Requesting the Conductor to suspend process ...
[ DONE ] Process with alias: HelloWorld is being suspended.

[ HELP ] Run the 'fugue status' command to view details and status of this process suspension.

This time, the command is successful and we can confirm the status with bob‘s default permission.

$ fugue status

Fugue Status Report for main-user/xxxxxxxx - Fri May 4 2018 3:48pm

State      Updated    Created    Account    FID/Alias    Flags    Last Message
---------  ---------  ---------  ---------  -----------  -------  --------------
Suspended  3:47pm     3:09pm     fugue      HelloWorld   -e       SUCCEEDED

Switching Back to Root to View the History

An additional component of the --do-as functionality is the attribution of commands, so while bob was the default user, the suspend command was issued as alice. This action is reflected in the history of the process (which we grabbed below).

First, let’s set the default user back to root in order to run the history command since neither bob nor alice has correct permissions.

Grab those root credentials you saved and issue a user set command:

fugue user set root Pxloym/tDxlf2sv22kbtMcMKUwxT/21vaVa/TbySjTE=

And let’s check the history of our process to see how attribution is noted.

$ fugue history HelloWorld

History Report for main-user/xxxxxxxx - Fri May 4 2018 3:50pm
HelloWorld (c8035e40-fc16-466d-ade2-42ac346bc269)

Type    Started    Work             User     Done As     Last Job Id       Last Updated    Status     Description
------  ---------  --------------   ------   ---------   ----------------  --------------  ---------  --------------
Event   3:47pm     FUGUE SUSPEND    bob      alice                                         SUCCEEDED  EventReceived
Event   3:46pm     FUGUE SUSPEND    bob      bob                                           FAILED     Unauthorized
Job     3:10pm     SYSTEM                                1525463238 (74)  3:47pm           SUCCEEDED  JobSucceeded
Job     3:10pm     RUN                                   1525461017 (1)   3:10pm           SUCCEEDED  JobSucceeded
Event   3:09pm     FUGUE RUN        alice    alice

Great job! We’ve demonstrated the enforcement of permissions for alice and bob. We’ve also demonstrated how you can create policy to delegate permission so users can issue commands as someone else with the --do-as flag.

Killing the Fugue Process

It’s time to wrap up this walkthrough, so let’s terminate our process with kill:

fugue kill -y HelloWorld

You’ll see output like this:

[ fugue kill ] Killing suspended process with Alias: HelloWorld

Requesting the Conductor to kill suspended composition with Alias: HelloWorld...
[ Done ] The conductor is killing the process with Alias: HelloWorld

You’re all done! You’ve written and applied an RBAC policy, enabled a new user, switched users, issued a command with --do-as, and demonstrated how Fugue prohibits or permits actions based on the policy set on the Conductor. Congratulations!

Next Steps

Now that you’re done with this walkthrough, you can revisit the overview on how to delegate permissions to issue commands as another user. If you’re ready for something else, maybe take a look at the Advanced RBAC: Governing Access to Processes and Accounts example. Or read up on the Fugue.System.Policy module in the Fugue Standard Library and try writing your own rules. And as always, reach out to support@fugue.co with any questions.