Use Instance Principals with OCI Python SDK

Use Instance Principals with OCI Python SDK

Introduction

In the last article, I’ve talked about How to use the OCI Python SDK to make API Calls where I used a config file to authenticate.

Now, I’d like to build up on that and show you an even better way to authenticate in your scripts using Instance Principals when your script is running from inside Oracle Cloud Infrastructure (OCI) tenant – on a Compute Instance.

With Instance Principals, you’re practically giving rights to resources (like a Compute VM  Instance) to access other resources or services in your OCI tenant.

In this example, I’m going to run a python script on a Compute VM in OCI that will have read access to all the resources in the tenant.

Define Instance Principals

Let’s create the configuration for the instance principals.

Create a Dynamic Group

Log in to your OCI Console and go to Identity -> Dynamic Groups -> Create Dynamic Group

Give your dynamic group a name, a description, and a matching rule.

The matching rule will identify the resource to which you want to give access to. In my example, I use the compartment id as a matching rule – so every resource from that particular compartment will be linked to this dynamic group. I will create a Compute VM inside that compartment and I will run my script from there.

You can define members of a dynamic group by:

    • compartment id
    • instance id
    • tag namespace and tag key
    • tag namespace, tag key, and tag value

Please find more info on this in the documentation.

Create Policy for Dynamic Group

In the console, go to Identity -> Policies -> Create Policy

Note: Be aware of what compartment you’re in when creating the policy – you can create all policies in the root compartment

Give your Policy name, a description, and a policy statement. 

In my example, I’m giving the dynamic group access to read all the resources in my tenancy.

The syntax for allowing access at the tenancy level is:

Allow dynamic-group <dynamic_group_name> to <verb> <resource-type> in tenancy

You can find more info on this in the documentation.

Using the Instance Principals

Now it’s time to use the instance principals when authenticating.

I’m going to create a new Compute VM Instance in the Compartment that I’ve referenced in the dynamic group and run my script from there.

This time, I don’t need a config file or even an API Key because my Compute VM instance has already been given access via the Instance Principals.

Remember when in the Dynamic Group I’ve referenced my Compartment in which I’ve created my VM Compute and I’ve written a Policy that granted read access across my tenancy to my Dynamic Group?

All I need to do to authenticate is to create a Signer:

def generate_signer_from_instance_principals(self):
  try:
    # get signer from instance principals token
    self.signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
  except Exception:
    print("There was an error while trying to get the Signer")
    raise SystemExit

  # generate config info from signer
  self.config = {'region': self.signer.region, 'tenancy': self.signer.tenancy_id}

and I will use this signer to create each client:

# initialize the IdentityClient with an empty config and only a signer
identity_client = oci.identity.IdentityClient(config = {}, signer=self.signer )

# initialize the ComputeClient with an empty config and only a signer
compute_client = oci.core.ComputeClient(config = {}, signer=self.signer)

Note: As config is not an optional parameter, I am passing an empty dict as config

Now I can call any API available in OCI!

Conclusions and Complete Solution

When you want to execute a python script from inside OCI, use Instance Principals for authentication purposes, it will simplify your life!

With Instance Principals, you’re authorizing instances to access services across your Oracle Cloud Infrastructure tenancy.

You can find below an example of a script using Instance Principals to list all the Compute VM Instances from a specific compartment:

import oci


class OCICalls(object):
    def __init__(self):
    
        # generate signer
        self.generate_signer_from_instance_principals()

        # call apis
        self.get_compute_list()
    
    def generate_signer_from_instance_principals(self):
        try:
            # get signer from instance principals token
            self.signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
        except Exception:
            print("There was an error while trying to get the Signer")
            raise SystemExit

        # generate config info from signer
        self.config = {'region': self.signer.region, 'tenancy': self.signer.tenancy_id}
        
    
    def get_compute_list(self):
        # initialize the IdentityClient with an empty config and only a signer
        identity_client = oci.identity.IdentityClient(config = {}, signer=self.signer )
        
        # initialize the ComputeClient with an empty config and only a signer
        compute_client = oci.core.ComputeClient(config = {}, signer=self.signer)
        
        # get the list of all compartments in my tenancy
        compartments = identity_client.list_compartments(self.config["tenancy"], compartment_id_in_subtree=True, access_level="ACCESSIBLE").data
         
        # find my compartment
        for compartment in compartments:
            if "test_compartment" in compartment.name:
                # get the list of all instances in my compartment
                instances = compute_client.list_instances(compartment.id).data
        
        print(f"My instances are: {instances}")
        
# Initiate process
OCICalls()

You can also find the code on my GitHub Repo.

Happy coding!

Resources

OCI Instance Principals Documentation

OCI Python SDK Github

OCI Python SDK Documentation

Image rights

Ionut Adrian Vladu

I enjoy building python scripts for…everything! I am a Cloud enthusiast and I like to keep up with technology. When I'm not behind a computer, I like taking photos -- Visit My 500px profile -- or sit back and enjoy Formula 1 race weekends. Currently, working as a Tech Cloud Specialist @ Oracle
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments