#How best to identify a module's caller?

1 messages · Page 1 of 1 (latest)

misty latch
#

I have two modules Service and Consumer in a repository:

daggerverse
├── .git
├── service
│   ├── dagger.json
│   └── main.go
└── consumer
    ├── dagger.json
    └── main.go

I would like the Service.GetInfo function to behave differently when it is called from the Consumer module compared to other modules/the cli.

I have been playing around passing the output of dag.CurrentModule().ID(ctx) as an input but I do not really want to hard code the value in the Service module.

Is there a way to retrieve the top level directory that contains both of them and hash it? Any other ideas on how to validate the caller's identity?

Thank you for your help!

frigid remnant
novel dune
#

That seems like a bad idea that you can inspect this. @misty latch could you just make it a boolean argument to your service function, to make the behavior you want configurable?

barren mountain
#

hm, that's not what that function does 🤔

#

parent is:

The value of the parent object of the function being called. If the function is top-level to the module, this is always an empty object.

#

it's intended to be used by the codegen, it essentially just gets the json representation of the "self" object

#

example snippet from dagger.gen.go

#

as far as i know, there's no way to get this information - intentionally.
if you could get this info, the caching would be wrong - having a function return different value based on who's calling means it wouldn't be safe to cache any function results ever

misty latch
#

I am going towards a ID/Accessor argument in the function so it should be able to cache everything properly.
We could make that a boolean but I was hoping for something more obfuscated that could be computed by the both the caller and service, e.g. by inspecting the other directories in the repository.

#

I'm thinking about maybe embedding the same file storing a random number but I'd still need to commit that to the repo instead of it being some sort of hash.

novel dune
#

@misty latch if you want to make it more obsfucated, that makes me curious what the goal is. Why do you need the function to behave differently based on who is calling it, in the first place?

misty latch
#

The service module is anything that has two levels of permissions, e.g. retrieving dev vs prod credentials, sending a private vs public message etc.
The official consumer module has got the full process we ideally want to do before using the service with elevated permissions.
However, users can use the service outside the official consumer, and have enough credentials to do the elevated actions since the credentials come from the ci environment.

The aim of identifying the caller would be to ensure users are aware they not using the official process.

Hence I'm thinking of doing either your boolean suggestion or a password of some sort (which I was hoping could be a property of the official module like its ID).

For illustration:

func New(cred *dagger.Secret) *Service { ... } 

func (m *Service) Elevated(
    // +optional
    IKnowWhatImDoing bool
) error { ... }

func (m *Service) Elevated(
    // +optional
    password string
) error {
    if password != elevatedPassword {
        return ErrUnauthorized
    }
    ...
}
tropic citrus
#

This is an important requirement for us too. As an enterprise we do have certain enforcements we want to perform based on caller (host or module). CI vs local machine for example.

novel dune
#

OK, please bear with me here... The general idea of Dagger is that the pipeline logic doesn't need to be segregated based on underlying environment (for example available credentials, machine identity etc), because it's easy to run the same logic in different environments - the functions will just get different arguments (or in the case of machine identity, things will just magically work or not)

#

But it seems that you're saying, your environment is not sufficiently segregated (ie. the local dev environment has enough privileges to access the same credentials as a production CI environment), so you want to simulate a more restricted environment in the pipeline logic

#

My general rule of thumb is: if you don't want a user or machine to be allowed to do something, don't give them the credentials to do it, at the infra level. Enforcing this at the pipeline logic level feels kind of like checking a user's password in client-side javascript in the browser

#

I have a feeling that you guys already know all this, so I'm probably missing something