Code Monkey home page Code Monkey logo

Comments (5)

devblackops avatar devblackops commented on May 20, 2024

Yes, I think we need some way to manage credentials that commands can run under.

One question is should plugin commands be able to access a global collection of credentials or should PoshBot separate them by plugin and only allow commands to access credentials associated with that plugin? The latter is more secure but potentially more cumbersome to manage. You may have multiple plugins that you've authored for your company and if you want to use the same credentials across plugins, you'd have to specify it in the configuration multiple times.

from poshbot.

RamblingCookieMonster avatar RamblingCookieMonster commented on May 20, 2024

Hmm - good question it might make sense to allow both, similar to statefuldata commands?

e.g.

Add-PoshBotRunAsCredential or whatever system stores the credential might have something similar to -Scope, allowing a user to specify if they want a credential to be available to everything, or a specific module.

For example:

  • If -Global switch specified, any plugin can access it
  • If -Module [string[]] specified, any plugin in the list can access it

from poshbot.

RamblingCookieMonster avatar RamblingCookieMonster commented on May 20, 2024

oh! if this is up for grabs, would be happy to help! some quick thoughts:

I see two general workflows:

  • PoshBot admin wants to always run command ABC with credential XYZ, doesn't want to revamp internals of the plugin command. Design would likely require a command-to-credential mapping file
  • PoshBot author wants to allow specifying a certain credential. Author will likely need to retrieve a PSCredential. Design would likely benefit from both (1) the option of a command-to-credential map, and (2) potentially the option to allow a user to specify the unique name of a credential to use

Might be over the top, just thinking off the top of my head

  • Where / how to serialize credentials
    • Typical DPAPI serialization to $PoshBotContext.ConfigurationDirectory or a subdirectory might make sense?
  • What other information to include
    • Username
    • Password
    • Optional? Unique Name (default to username, error and require force if existing found regardless of whether Name was provided or not)
    • AllowedModules? Array, use like operator when evaluating whether a plugin can use it (* for global)
    • Roles? Array, user calling command must be in this role to retrieve credential
    • Description? Just for record keeping / details if desired
    • Tags? A way for PoshBot authors to find a credential that their command needs, without forcing a user to specify a certain pre-determined name
  • How to manage associating a command with a credential. Might need a config file mapping commands to credentials

Down the line, this could be used with data about a remote node to execute on, but IMHO it makes sense to keep that separate and let folks mix and match creds/remote details as needed. Or it could be combined. I see benefits / caveats to both...

Cheers!

from poshbot.

devblackops avatar devblackops commented on May 20, 2024

We may be able to reuse (with some tweaks) the existing functionality in PoshBot that allows plugin authors to specify that a command parameter by dynamically resolved from the bot configuration. The existing logic could probably be extended for plugin authors to declare that a command be run (as a job) with specific credentials that are stored under the PluginConfiguration property of the bot configuration.

The way it currently works

PoshBot's Get-PoshBotConfiguration and Save-PoshBotConfiguration functions use Joel's Configuration module so it already handles serializing/deserialing credentials and secure strings (with the caveat that the user getting/saving the config must also be the user running PoshBot).
To use those values inside your plugin, you would decorate the parameter with [PoshBot.FromConfig()] and PoshBot would look in the appropriate key (plugin name) and subkey (parameter name) and dynamically insert that value as a named parameter when executing the command as a job.
This doesn't solve running the entire command as another user but does provide a mechanism to pass secrets and other data to plugin commands that you can't (or don't want to) distribute with the plugin.

PoshBot.psd1
@{
    ###
    # other bot properties omitted
    ###    
    PluginConfiguration = @{
        MyModule = @{
            Credential = (PSCredential "joeuser" "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000060ae863578849c4680a57d65f2994eff00000000020000000000106600000001000020000000cd8c90628fc9f7fd332869a0e30eec41cbje8c531618375f22bfa84a2a53e132000000000e80000000020000200000003b7027c1f5577bd36f7f9c87db7bb427f4808466758eb9a579e36be9bc49b3481000000092223e3261d78e6547ed0f799f5462eb400000008hpddfa3619fcc7b56bb2571b8cc9405740bf266e1fd8fc79b9nj1203ad9058d19a73eb75f5d977ef4478dc9f207f21e19c95affd1d44eca0b405f879e3c98nu")
        }
    }
}
MyModule.psm1
function Get-Foo {
    [cmdletbinding()]
    param(
        [PoshBot.FromConfig()]
        [parameter(mandatory)]
        [string]$Credential
    )

    # Do something useful with $Credential
}

How it could work

This would be a breaking change to how plugin configuration is currently stored but we could modify the structure to resemble:

PoshBot.psd1
@{
    ###
    # other bot properties omitted
    ###    
    PluginConfiguration = @{
        # Global variables that any plugin can reference
        Global = @{
            SharedCred1 = (PSCredential "shared1" "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000060ae863578849c4680a57d65f2994eff00000000020000000000106600000001000020000000cd8c90628fc9f7fd332869a0e30eec41cbje8c531618375f22bfa84a2a53e132000000000e80000000020000200000003b7027c1f5577bd36f7f9c87db7bb427f4808466758eb9a579e36be9bc49b3481000000092223e3261d78e6547ed0f799f5462eb400000008hpddfa3619fcc7b56bb2571b8cc9405740bf266e1fd8fc79b9nj1203ad9058d19a73eb75f5d977ef4478dc9f207f21e19c95affd1d44eca0b405f879e3c98nu")
            SharedCred2 = (PSCredential "shared2" "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000060ae863578849c4680a57d65f2994eff00000000020000000000106600000001000020000000cd8c90628fc9f7fd332869a0e30eec41cbje8c531618375f22bfa84a2a53e132000000000e80000000020000200000003b7027c1f5577bd36f7f9c87db7bb427f4808466758eb9a579e36be9bc49b3481000000092223e3261d78e6547ed0f799f5462eb400000008hpddfa3619fcc7b56bb2571b8cc9405740bf266e1fd8fc79b9nj1203ad9058d19a73eb75f5d977ef4478dc9f207f21e19c95affd1d44eca0b405f879e3c98nu")
        }

        # Variables only accessible to the plugin
        MyModule = @{
            Credential1 = (PSCredential "joeuser" "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000060ae863578849c4680a57d65f2994eff00000000020000000000106600000001000020000000cd8c90628fc9f7fd332869a0e30eec41cbje8c531618375f22bfa84a2a53e132000000000e80000000020000200000003b7027c1f5577bd36f7f9c87db7bb427f4808466758eb9a579e36be9bc49b3481000000092223e3261d78e6547ed0f799f5462eb400000008hpddfa3619fcc7b56bb2571b8cc9405740bf266e1fd8fc79b9nj1203ad9058d19a73eb75f5d977ef4478dc9f207f21e19c95affd1d44eca0b405f879e3c98nu")
            MyOtherCredential = (PSCredential "sallysmith" "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000060ae863578849c4680a57d65f2994eff00000000020000000000106600000001000020000000cd8c90628fc9f7fd332869a0e30eec41cbje8c531618375f22bfa84a2a53e132000000000e80000000020000200000003b7027c1f5577bd36f7f9c87db7bb427f4808466758eb9a579e36be9bc49b3481000000092223e3261d78e6547ed0f799f5462eb400000008hpddfa3619fcc7b56bb2571b8cc9405740bf266e1fd8fc79b9nj1203ad9058d19a73eb75f5d977ef4478dc9f207f21e19c95affd1d44eca0b405f879e3c98nu")
            }
        }
    }
}

You would then reference these variables in your plugin command by using the [PoshBot.BotCommand()] and [PoshBot.FromConfig()] custom attributes.

function Get-Foo {
    # Run this command as a job using the 'SharedCred2' value from
    # the global plugin configuration scope
    [PoshBot.BotCommand(
        CommandName = 'foo',
        RunAs = 'SharedCred2',
        Scope = 'Global'
    )]
    [cmdletbinding()]
    param(
        # Go get the 'Credential1` value from the plugin scope of the bot configuration
        # 'Scope = 'Plugin' would be implicit
        [PoshBot.FromConfig('Credential1')]
        [pscredential]$Credential

        # Go get the 'SharedCred1' value from the global plugin configuration scope
        [PoshBot.FromConfig(
            'SharedCred1',
            Scope = 'Global'
        )]
        [pscredential]$SharedCredential
    )    
}

I like the idea of given the bot admin the ability to specify the credentials a command will run under without mucking with the plugin itself.
Perhaps another property could be added to the bot configuration like the following:

PoshBot.psd1

@{
    # Control under what credential plugin commands are run under.
    # Can specify individual commands or all commands in a plugin.
    RunAs = @{
        'MyPlugin:MyCommand' = 'SharedCred1`
        'MyPlugin:Foo' = 'SharedCred2'
        'MyOtherPlugin:*' = 'SharedCred1'
    }
    PluginConfiguration = @{
        # Global variables that any plugin can reference
        Global = @{
            SharedCred1 = (PSCredential "shared1" "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000060ae863578849c4680a57d65f2994eff00000000020000000000106600000001000020000000cd8c90628fc9f7fd332869a0e30eec41cbje8c531618375f22bfa84a2a53e132000000000e80000000020000200000003b7027c1f5577bd36f7f9c87db7bb427f4808466758eb9a579e36be9bc49b3481000000092223e3261d78e6547ed0f799f5462eb400000008hpddfa3619fcc7b56bb2571b8cc9405740bf266e1fd8fc79b9nj1203ad9058d19a73eb75f5d977ef4478dc9f207f21e19c95affd1d44eca0b405f879e3c98nu")
            SharedCred2 = (PSCredential "shared2" "01000000d08c9ddf0115d1118c7a00c04fc297eb0100000060ae863578849c4680a57d65f2994eff00000000020000000000106600000001000020000000cd8c90628fc9f7fd332869a0e30eec41cbje8c531618375f22bfa84a2a53e132000000000e80000000020000200000003b7027c1f5577bd36f7f9c87db7bb427f4808466758eb9a579e36be9bc49b3481000000092223e3261d78e6547ed0f799f5462eb400000008hpddfa3619fcc7b56bb2571b8cc9405740bf266e1fd8fc79b9nj1203ad9058d19a73eb75f5d977ef4478dc9f207f21e19c95affd1d44eca0b405f879e3c98nu")
        }
    }
}

Sorry for the super long response.
It's late and I hope this makes sense 😫

I'm totally open to storing this data outside the main bot configuration if that makes sense as well.

from poshbot.

stale avatar stale commented on May 20, 2024

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

from poshbot.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.