]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
qa: STS Web Identity task files 37503/head
authorKalpesh Pandya <kapandya@redhat.com>
Fri, 22 May 2020 20:58:53 +0000 (02:28 +0530)
committerroot <root@localhost.localdomain>
Sat, 28 Nov 2020 23:22:19 +0000 (04:52 +0530)
This commit comprises of 3 things:
1) Keycloak task (to bring up keycloak in teuthology inorder to execute Assume_Role_With_Web_Identity tests).
2) The required changes for this in s3tests.py which consists of writing some parameters to configuration file.
3) The yaml files which executes these tasks.

Signed-off-by: Kalpesh Pandya <kapandya@redhat.com>
qa/suites/rgw/sts/tasks/ststests.yaml
qa/suites/rgw/sts/tasks/webidentity.yaml [new file with mode: 0644]
qa/tasks/keycloak.py [new file with mode: 0644]
qa/tasks/s3tests.py

index e5c52737e3af8564b841a3a813e81b3df82211b0..10c2f2aed780a2d1ca1888866e9da74eadc05a04 100644 (file)
@@ -1,8 +1,9 @@
 tasks:
 - s3tests:
     client.0:
-      extra_attrs: ['sts_test']
-      force-branch: master
+      sts_tests: True
+      extra_attrs: ["test_of_sts"]
+      force-branch: ceph-master
       rgw_server: client.0
 overrides:
   ceph:
diff --git a/qa/suites/rgw/sts/tasks/webidentity.yaml b/qa/suites/rgw/sts/tasks/webidentity.yaml
new file mode 100644 (file)
index 0000000..61427f3
--- /dev/null
@@ -0,0 +1,17 @@
+tasks:
+- tox: [ client.0 ]
+- keycloak:
+    client.0:
+      keycloak_version: 11.0.0
+- s3tests:
+    client.0:
+      sts_tests: True
+      force-branch: ceph-master
+      rgw_server: client.0
+      extra_attrs: ['webidentity_test']
+overrides:
+  ceph:
+    conf:
+      client:
+              rgw sts key: abcdefghijklmnop
+              rgw s3 auth use sts: true
diff --git a/qa/tasks/keycloak.py b/qa/tasks/keycloak.py
new file mode 100644 (file)
index 0000000..0f1fc9d
--- /dev/null
@@ -0,0 +1,335 @@
+"""
+Deploy and configure Keycloak for Teuthology
+"""
+import contextlib
+import logging
+import os
+
+from teuthology import misc as teuthology
+from teuthology import contextutil
+from teuthology.orchestra import run
+from teuthology.exceptions import ConfigError
+
+log = logging.getLogger(__name__)
+
+def get_keycloak_version(config):
+    for client, client_config in config.items():
+        if 'keycloak_version' in client_config:
+            keycloak_version = client_config.get('keycloak_version')
+    return keycloak_version
+
+def get_keycloak_dir(ctx, config):
+    keycloak_version = get_keycloak_version(config)
+    current_version = 'keycloak-'+keycloak_version
+    return '{tdir}/{ver}'.format(tdir=teuthology.get_testdir(ctx),ver=current_version)
+
+def run_in_keycloak_dir(ctx, client, config, args, **kwargs):
+    return ctx.cluster.only(client).run(
+        args=[ 'cd', get_keycloak_dir(ctx,config), run.Raw('&&'), ] + args,
+        **kwargs
+    )
+
+def get_toxvenv_dir(ctx):
+    return ctx.tox.venv_path
+
+def toxvenv_sh(ctx, remote, args, **kwargs):
+    activate = get_toxvenv_dir(ctx) + '/bin/activate'
+    return remote.sh(['source', activate, run.Raw('&&')] + args, **kwargs)
+
+@contextlib.contextmanager
+def install_packages(ctx, config):
+    """
+    Downloading the two required tar files
+    1. Keycloak
+    2. Wildfly (Application Server)
+    """
+    assert isinstance(config, dict)
+    log.info('Installing packages for Keycloak...')
+
+    for (client, _) in config.items():
+        (remote,) = ctx.cluster.only(client).remotes.keys()
+        test_dir=teuthology.get_testdir(ctx)
+        current_version = get_keycloak_version(config)
+        link1 = 'https://downloads.jboss.org/keycloak/'+current_version+'/keycloak-'+current_version+'.tar.gz'
+        toxvenv_sh(ctx, remote, ['wget', link1])
+        
+        file1 = 'keycloak-'+current_version+'.tar.gz'
+        toxvenv_sh(ctx, remote, ['tar', '-C', test_dir, '-xvzf', file1])
+
+        link2 ='https://downloads.jboss.org/keycloak/'+current_version+'/adapters/keycloak-oidc/keycloak-wildfly-adapter-dist-'+current_version+'.tar.gz' 
+        toxvenv_sh(ctx, remote, ['cd', '{tdir}'.format(tdir=get_keycloak_dir(ctx,config)), run.Raw('&&'), 'wget', link2])
+        
+        file2 = 'keycloak-wildfly-adapter-dist-'+current_version+'.tar.gz'
+        toxvenv_sh(ctx, remote, ['tar', '-C', '{tdir}'.format(tdir=get_keycloak_dir(ctx,config)), '-xvzf', '{tdr}/{file}'.format(tdr=get_keycloak_dir(ctx,config),file=file2)])
+
+    try:
+        yield
+    finally:
+        log.info('Removing packaged dependencies of Keycloak...')
+        for client in config:
+            ctx.cluster.only(client).run(
+                args=['rm', '-rf', '{tdir}'.format(tdir=get_keycloak_dir(ctx,config))],
+            )
+
+@contextlib.contextmanager
+def build(ctx,config):
+    """
+    Build process which needs to be done before starting a server.
+    """
+    assert isinstance(config, dict)
+    log.info('Building Keycloak...')
+    for (client,_) in config.items():
+        run_in_keycloak_dir(ctx, client, config,['cd', 'bin', run.Raw('&&'), './jboss-cli.sh', '--file=adapter-elytron-install-offline.cli'])
+    try:
+        yield
+    finally:
+        pass
+
+@contextlib.contextmanager
+def run_keycloak(ctx,config):
+    """
+    This includes two parts:
+    1. Adding a user to keycloak which is actually used to log in when we start the server and check in browser.
+    2. Starting the server.
+    """
+    assert isinstance(config, dict)
+    log.info('Bringing up Keycloak...')
+    for (client,_) in config.items():
+        (remote,) = ctx.cluster.only(client).remotes.keys()
+        
+        ctx.cluster.only(client).run(
+            args=[
+                '{tdir}/bin/add-user-keycloak.sh'.format(tdir=get_keycloak_dir(ctx,config)),
+                '-r', 'master',
+                '-u', 'admin',
+                '-p', 'admin',
+            ],
+        )
+
+        toxvenv_sh(ctx, remote, ['cd', '{tdir}/bin'.format(tdir=get_keycloak_dir(ctx,config)), run.Raw('&&'), './standalone.sh', run.Raw('&'), 'exit'])
+    try:
+        yield
+    finally:
+        log.info('Stopping Keycloak Server...')
+
+        for (client, _) in config.items():
+            (remote,) = ctx.cluster.only(client).remotes.keys()
+            toxvenv_sh(ctx, remote, ['cd', '{tdir}/bin'.format(tdir=get_keycloak_dir(ctx,config)), run.Raw('&&'), './jboss-cli.sh', '--connect', 'command=:shutdown'])
+
+@contextlib.contextmanager
+def run_admin_cmds(ctx,config):
+    """
+    Running Keycloak Admin commands(kcadm commands) in order to get the token, aud value, thumbprint and realm name.
+    """
+    assert isinstance(config, dict)
+    log.info('Running admin commands...')
+    for (client,_) in config.items():
+        (remote,) = ctx.cluster.only(client).remotes.keys()
+
+        remote.run(
+           args=[
+                '{tdir}/bin/kcadm.sh'.format(tdir=get_keycloak_dir(ctx,config)),
+                'config', 'credentials',
+                '--server', 'http://localhost:8080/auth',
+                '--realm', 'master',
+                '--user', 'admin',
+                '--password', 'admin',
+                '--client', 'admin-cli',
+                ],
+            )
+
+        realm_name='demorealm'
+        realm='realm={}'.format(realm_name)
+
+        remote.run(
+           args=[
+                '{tdir}/bin/kcadm.sh'.format(tdir=get_keycloak_dir(ctx,config)),
+                'create', 'realms',
+                '-s', realm,
+                '-s', 'enabled=true',
+                '-s', 'accessTokenLifespan=1800',
+                '-o',
+            ],
+        )
+
+        client_name='my_client'
+        client='clientId={}'.format(client_name)
+
+        remote.run(
+           args=[
+                '{tdir}/bin/kcadm.sh'.format(tdir=get_keycloak_dir(ctx,config)),
+                'create', 'clients',
+                '-r', realm_name,
+                '-s', client,
+                '-s', 'redirectUris=["http://localhost:8080/myapp/*"]',
+            ],
+        )
+
+        ans1= toxvenv_sh(ctx, remote, 
+                 [
+                  'cd', '{tdir}/bin'.format(tdir=get_keycloak_dir(ctx,config)), run.Raw('&&'), 
+                  './kcadm.sh', 'get', 'clients', 
+                  '-r', realm_name, 
+                  '-F', 'id,clientId', run.Raw('|'), 
+                  'jq', '-r', '.[] | select (.clientId == "my_client") | .id'
+                 ])
+
+        pre0=ans1.rstrip()
+        pre1="clients/{}".format(pre0)
+
+        remote.run(
+            args=[
+                '{tdir}/bin/kcadm.sh'.format(tdir=get_keycloak_dir(ctx,config)),
+                'update', pre1,
+                '-r', realm_name,
+                '-s', 'enabled=true',
+                '-s', 'serviceAccountsEnabled=true',
+                '-s', 'redirectUris=["http://localhost:8080/myapp/*"]',
+            ],
+        )
+
+        ans2= pre1+'/client-secret'
+
+        out2= toxvenv_sh(ctx, remote, 
+                 [
+                  'cd', '{tdir}/bin'.format(tdir=get_keycloak_dir(ctx,config)), run.Raw('&&'), 
+                  './kcadm.sh', 'get', ans2, 
+                  '-r', realm_name, 
+                  '-F', 'value'
+                 ])
+
+        ans0= '{client}:{secret}'.format(client=client_name,secret=out2[15:51])
+        ans3= 'client_secret={}'.format(out2[15:51])
+        clientid='client_id={}'.format(client_name)
+
+        out3= toxvenv_sh(ctx, remote, 
+                 [
+                  'curl', '-k', '-v', 
+                  '-X', 'POST', 
+                  '-H', 'Content-Type:application/x-www-form-urlencoded', 
+                  '-d', 'scope=openid', 
+                  '-d', 'grant_type=client_credentials', 
+                  '-d', clientid, 
+                  '-d', ans3, 
+                  'http://localhost:8080/auth/realms/'+realm_name+'/protocol/openid-connect/token', run.Raw('|'), 
+                  'jq', '-r', '.access_token'
+                 ])
+
+        pre2=out3.rstrip()
+        acc_token= 'token={}'.format(pre2)
+        ans4= '{}'.format(pre2)
+
+        out4= toxvenv_sh(ctx, remote, 
+                 [
+                  'curl', '-k', '-v', 
+                  '-X', 'GET', 
+                  '-H', 'Content-Type:application/x-www-form-urlencoded', 
+                  'http://localhost:8080/auth/realms/'+realm_name+'/protocol/openid-connect/certs', run.Raw('|'), 
+                  'jq', '-r', '.keys[].x5c[]'
+                 ])
+
+        pre3=out4.rstrip()
+        cert_value='{}'.format(pre3)
+        start_value= "-----BEGIN CERTIFICATE-----\n"
+        end_value= "\n-----END CERTIFICATE-----"
+        user_data=""
+        user_data+=start_value
+        user_data+=cert_value
+        user_data+=end_value
+
+        remote.write_file(
+            path='{tdir}/bin/certificate.crt'.format(tdir=get_keycloak_dir(ctx,config)),
+            data=user_data
+            )
+
+        out5= toxvenv_sh(ctx, remote, 
+                 [
+                  'openssl', 'x509', 
+                  '-in', '{tdir}/bin/certificate.crt'.format(tdir=get_keycloak_dir(ctx,config)), 
+                  '--fingerprint', '--noout', '-sha1'
+                 ])
+
+        pre_ans= '{}'.format(out5[17:76])
+        ans5=""
+
+        for character in pre_ans:
+            if(character!=':'):
+                ans5+=character
+
+        out6= toxvenv_sh(ctx, remote, 
+                 [
+                  'curl', '-k', '-v', 
+                  '-X', 'POST', 
+                  '-u', ans0, 
+                  '-d', acc_token, 
+                  'http://localhost:8080/auth/realms/'+realm_name+'/protocol/openid-connect/token/introspect', run.Raw('|'), 
+                  'jq', '-r', '.aud'
+                 ])
+
+        ans6=out6.rstrip()
+
+        os.environ['TOKEN']=ans4
+        os.environ['THUMBPRINT']=ans5
+        os.environ['AUD']=ans6
+        os.environ['KC_REALM']=realm_name
+
+    try:
+        yield
+    finally:
+        log.info('Removing certificate.crt file...')
+        for (client,_) in config.items():
+            (remote,) = ctx.cluster.only(client).remotes.keys()
+            remote.run(
+                 args=['rm', '-f',
+                       '{tdir}/bin/certificate.crt'.format(tdir=get_keycloak_dir(ctx,config)),
+                 ],
+                 )
+
+@contextlib.contextmanager
+def task(ctx,config):
+    """
+    To run keycloak the prerequisite is to run the tox task. Following is the way how to run
+    tox and then keycloak::
+
+    tasks:
+    - tox: [ client.0 ]
+    - keycloak:
+        client.0:
+            keycloak_version: 11.0.0
+   
+    To pass extra arguments to nose (e.g. to run a certain test)::
+
+    tasks:
+    - tox: [ client.0 ]
+    - keycloak:
+        client.0:
+            keycloak_version: 11.0.0
+    - s3tests:
+        client.0:
+          extra_attrs: ['webidentity_test']
+    """
+    assert config is None or isinstance(config, list) \
+        or isinstance(config, dict), \
+        "task keycloak only supports a list or dictionary for configuration"
+
+    if not hasattr(ctx, 'tox'):
+        raise ConfigError('keycloak must run after the tox task')
+
+    all_clients = ['client.{id}'.format(id=id_)
+                   for id_ in teuthology.all_roles_of_type(ctx.cluster, 'client')]
+    if config is None:
+        config = all_clients
+    if isinstance(config, list):
+        config = dict.fromkeys(config)
+
+    log.debug('Keycloak config is %s', config)
+    
+    with contextutil.nested(
+        lambda: install_packages(ctx=ctx, config=config),
+        lambda: build(ctx=ctx, config=config),
+        lambda: run_keycloak(ctx=ctx, config=config),
+        lambda: run_admin_cmds(ctx=ctx, config=config),
+        ):
+        yield
+
index c0d5af5f3f0e6e06c8d8c70010090a53c1865ae3..d87c2ab0a4303a279fcd69d7046857343268de02 100644 (file)
@@ -97,93 +97,163 @@ def create_users(ctx, config):
     assert isinstance(config, dict)
     log.info('Creating rgw users...')
     testdir = teuthology.get_testdir(ctx)
-    users = {'s3 main': 'foo', 's3 alt': 'bar', 's3 tenant': 'testx$tenanteduser', 'iam': 'foobar'}
-    for client in config['clients']:
-        s3tests_conf = config['s3tests_conf'][client]
-        s3tests_conf.setdefault('fixtures', {})
-        s3tests_conf['fixtures'].setdefault('bucket prefix', 'test-' + client + '-{random}-')
-        for section, user in users.items():
-            _config_user(s3tests_conf, section, '{user}.{client}'.format(user=user, client=client))
-            log.debug('Creating user {user} on {host}'.format(user=s3tests_conf[section]['user_id'], host=client))
-            cluster_name, daemon_type, client_id = teuthology.split_role(client)
-            client_with_id = daemon_type + '.' + client_id
-            if section=='iam':
-                ctx.cluster.only(client).run(
-                    args=[
-                        'adjust-ulimits',
-                        'ceph-coverage',
-                        '{tdir}/archive/coverage'.format(tdir=testdir),
-                        'radosgw-admin',
-                        '-n', client_with_id,
-                        'user', 'create',
-                        '--uid', s3tests_conf[section]['user_id'],
-                        '--display-name', s3tests_conf[section]['display_name'],
-                        '--access-key', s3tests_conf[section]['access_key'],
-                        '--secret', s3tests_conf[section]['secret_key'],
-                        '--cluster', cluster_name,
-                    ],
-                )
-                ctx.cluster.only(client).run(
-                    args=[
-                        'adjust-ulimits',
-                        'ceph-coverage',
-                        '{tdir}/archive/coverage'.format(tdir=testdir),
-                        'radosgw-admin',
-                        '-n', client_with_id,
-                        'caps', 'add',
-                        '--uid', s3tests_conf[section]['user_id'],
-                        '--caps', 'user-policy=*',
-                        '--cluster', cluster_name,
-                    ],
-                )
-                ctx.cluster.only(client).run(
-                    args=[
-                        'adjust-ulimits',
-                        'ceph-coverage',
-                        '{tdir}/archive/coverage'.format(tdir=testdir),
-                        'radosgw-admin',
-                        '-n', client_with_id,
-                        'caps', 'add',
-                        '--uid', s3tests_conf[section]['user_id'],
-                        '--caps', 'roles=*',
-                        '--cluster', cluster_name,
-                    ],
-                )
-            else: 
+    
+    if ctx.sts_variable:
+        users = {'s3 main': 'foo', 's3 alt': 'bar', 's3 tenant': 'testx$tenanteduser', 'iam': 'foobar'}
+        for client in config['clients']:
+            s3tests_conf = config['s3tests_conf'][client]
+            s3tests_conf.setdefault('fixtures', {})
+            s3tests_conf['fixtures'].setdefault('bucket prefix', 'test-' + client + '-{random}-')
+            for section, user in users.items():
+                _config_user(s3tests_conf, section, '{user}.{client}'.format(user=user, client=client))
+                log.debug('Creating user {user} on {host}'.format(user=s3tests_conf[section]['user_id'], host=client))
+                cluster_name, daemon_type, client_id = teuthology.split_role(client)
+                client_with_id = daemon_type + '.' + client_id
+                if section=='iam':
+                    ctx.cluster.only(client).run(
+                        args=[
+                            'adjust-ulimits',
+                            'ceph-coverage',
+                            '{tdir}/archive/coverage'.format(tdir=testdir),
+                            'radosgw-admin',
+                            '-n', client_with_id,
+                            'user', 'create',
+                            '--uid', s3tests_conf[section]['user_id'],
+                            '--display-name', s3tests_conf[section]['display_name'],
+                            '--access-key', s3tests_conf[section]['access_key'],
+                            '--secret', s3tests_conf[section]['secret_key'],
+                            '--cluster', cluster_name,
+                        ],
+                    )
+                    ctx.cluster.only(client).run(
+                        args=[
+                            'adjust-ulimits',
+                            'ceph-coverage',
+                            '{tdir}/archive/coverage'.format(tdir=testdir),
+                            'radosgw-admin',
+                            '-n', client_with_id,
+                            'caps', 'add',
+                            '--uid', s3tests_conf[section]['user_id'],
+                            '--caps', 'user-policy=*',
+                            '--cluster', cluster_name,
+                        ],
+                    )
+                    ctx.cluster.only(client).run(
+                        args=[
+                            'adjust-ulimits',
+                            'ceph-coverage',
+                            '{tdir}/archive/coverage'.format(tdir=testdir),
+                            'radosgw-admin',
+                            '-n', client_with_id,
+                            'caps', 'add',
+                            '--uid', s3tests_conf[section]['user_id'],
+                            '--caps', 'roles=*',
+                            '--cluster', cluster_name,
+                        ],
+                    )
+                    ctx.cluster.only(client).run(
+                        args=[
+                            'adjust-ulimits',
+                            'ceph-coverage',
+                            '{tdir}/archive/coverage'.format(tdir=testdir),
+                            'radosgw-admin',
+                            '-n', client_with_id,
+                            'caps', 'add',
+                            '--uid', s3tests_conf[section]['user_id'],
+                            '--caps', 'oidc-provider=*',
+                            '--cluster', cluster_name,
+                        ],
+                    )
+
+                else: 
+                    ctx.cluster.only(client).run(
+                        args=[
+                            'adjust-ulimits',
+                            'ceph-coverage',
+                            '{tdir}/archive/coverage'.format(tdir=testdir),
+                            'radosgw-admin',
+                            '-n', client_with_id,
+                            'user', 'create',
+                            '--uid', s3tests_conf[section]['user_id'],
+                            '--display-name', s3tests_conf[section]['display_name'],
+                            '--access-key', s3tests_conf[section]['access_key'],
+                            '--secret', s3tests_conf[section]['secret_key'],
+                            '--email', s3tests_conf[section]['email'],
+                            '--caps', 'user-policy=*',
+                            '--cluster', cluster_name,
+                        ],
+                    )
+                    ctx.cluster.only(client).run(
+                        args=[
+                            'adjust-ulimits',
+                            'ceph-coverage',
+                            '{tdir}/archive/coverage'.format(tdir=testdir),
+                            'radosgw-admin',
+                            '-n', client_with_id,
+                            'mfa', 'create',
+                            '--uid', s3tests_conf[section]['user_id'],
+                            '--totp-serial', s3tests_conf[section]['totp_serial'],
+                            '--totp-seed', s3tests_conf[section]['totp_seed'],
+                            '--totp-seconds', s3tests_conf[section]['totp_seconds'],
+                            '--totp-window', '8',
+                            '--totp-seed-type', 'base32',
+                            '--cluster', cluster_name,
+                        ],
+                    )
+
+    else:
+        users = {'s3 main': 'foo', 's3 alt': 'bar', 's3 tenant': 'testx$tenanteduser'}
+        for client in config['clients']:
+            s3tests_conf = config['s3tests_conf'][client]
+            s3tests_conf.setdefault('fixtures', {})
+            s3tests_conf['fixtures'].setdefault('bucket prefix', 'test-' + client + '-{random}-')
+            for section, user in users.items():
+                _config_user(s3tests_conf, section, '{user}.{client}'.format(user=user, client=client))
+                log.debug('Creating user {user} on {host}'.format(user=s3tests_conf[section]['user_id'], host=client))
+                cluster_name, daemon_type, client_id = teuthology.split_role(client)
+                client_with_id = daemon_type + '.' + client_id
                 ctx.cluster.only(client).run(
-                    args=[
-                        'adjust-ulimits',
-                        'ceph-coverage',
-                        '{tdir}/archive/coverage'.format(tdir=testdir),
-                        'radosgw-admin',
-                        '-n', client_with_id,
-                        'user', 'create',
-                        '--uid', s3tests_conf[section]['user_id'],
-                        '--display-name', s3tests_conf[section]['display_name'],
-                        '--access-key', s3tests_conf[section]['access_key'],
-                        '--secret', s3tests_conf[section]['secret_key'],
-                        '--email', s3tests_conf[section]['email'],
-                        '--caps', 'user-policy=*',
-                        '--cluster', cluster_name,
-                    ],
-                )
+                        args=[
+                            'adjust-ulimits',
+                            'ceph-coverage',
+                            '{tdir}/archive/coverage'.format(tdir=testdir),
+                            'radosgw-admin',
+                            '-n', client_with_id,
+                            'user', 'create',
+                            '--uid', s3tests_conf[section]['user_id'],
+                            '--display-name', s3tests_conf[section]['display_name'],
+                            '--access-key', s3tests_conf[section]['access_key'],
+                            '--secret', s3tests_conf[section]['secret_key'],
+                            '--email', s3tests_conf[section]['email'],
+                            '--caps', 'user-policy=*',
+                            '--cluster', cluster_name,
+                        ],
+                    )
                 ctx.cluster.only(client).run(
-                    args=[
-                        'adjust-ulimits',
-                        'ceph-coverage',
-                        '{tdir}/archive/coverage'.format(tdir=testdir),
-                        'radosgw-admin',
-                        '-n', client_with_id,
-                        'mfa', 'create',
-                        '--uid', s3tests_conf[section]['user_id'],
-                        '--totp-serial', s3tests_conf[section]['totp_serial'],
-                        '--totp-seed', s3tests_conf[section]['totp_seed'],
-                        '--totp-seconds', s3tests_conf[section]['totp_seconds'],
-                        '--totp-window', '8',
-                        '--totp-seed-type', 'base32',
-                        '--cluster', cluster_name,
-                    ],
-                )
+                        args=[
+                            'adjust-ulimits',
+                            'ceph-coverage',
+                            '{tdir}/archive/coverage'.format(tdir=testdir),
+                            'radosgw-admin',
+                            '-n', client_with_id,
+                            'mfa', 'create',
+                            '--uid', s3tests_conf[section]['user_id'],
+                            '--totp-serial', s3tests_conf[section]['totp_serial'],
+                            '--totp-seed', s3tests_conf[section]['totp_seed'],
+                            '--totp-seconds', s3tests_conf[section]['totp_seconds'],
+                            '--totp-window', '8',
+                            '--totp-seed-type', 'base32',
+                            '--cluster', cluster_name,
+                        ],
+                    )
+
+    if "TOKEN" in os.environ:
+        s3tests_conf.setdefault('webidentity', {})
+        s3tests_conf['webidentity'].setdefault('token',os.environ['TOKEN'])
+        s3tests_conf['webidentity'].setdefault('aud',os.environ['AUD'])
+        s3tests_conf['webidentity'].setdefault('thumbprint',os.environ['THUMBPRINT'])
+        s3tests_conf['webidentity'].setdefault('KC_REALM',os.environ['KC_REALM'])
+
     try:
         yield
     finally:
@@ -332,13 +402,12 @@ def run_tests(ctx, config):
         else:
             args += ['REQUESTS_CA_BUNDLE=/etc/pki/tls/certs/ca-bundle.crt']
         # civetweb > 1.8 && beast parsers are strict on rfc2616
-        attrs = ["!fails_on_rgw", "!lifecycle_expiration", "!fails_strict_rfc2616","!s3select","!sts_test"]
+        attrs = ["!fails_on_rgw", "!lifecycle_expiration", "!fails_strict_rfc2616","!s3select","!test_of_sts","!webidentity_test"]
         if client_config.get('calling-format') != 'ordinary':
             attrs += ['!fails_with_subdomain']
        
         if 'extra_attrs' in client_config:
-            attrs = client_config.get('extra_attrs')
-
+            attrs = client_config.get('extra_attrs') 
         args += [
             '{tdir}/s3-tests/virtualenv/bin/python'.format(tdir=testdir),
             '-m', 'nose',
@@ -439,6 +508,17 @@ def task(ctx, config):
               extra_args: ['test_s3:test_object_acl_grand_public_read']
             client.1:
               extra_args: ['--exclude', 'test_100_continue']
+
+    To run any sts-tests don't forget to set a config variable named 'sts_tests' to 'True' as follows::
+
+        tasks:
+        - ceph:
+        - rgw: [client.0]
+        - s3tests:
+            client.0:
+              sts_tests: True
+              rgw_server: client.0
+
     """
     assert hasattr(ctx, 'rgw'), 's3tests must run after the rgw task'
     assert config is None or isinstance(config, list) \
@@ -462,26 +542,80 @@ def task(ctx, config):
     log.debug('s3tests config is %s', config)
 
     s3tests_conf = {}
-    for client in clients:
-        endpoint = ctx.rgw.role_endpoints.get(client)
-        assert endpoint, 's3tests: no rgw endpoint for {}'.format(client)
-
-        s3tests_conf[client] = ConfigObj(
-            indent_type='',
-            infile={
-                'DEFAULT':
-                    {
-                    'port'      : endpoint.port,
-                    'is_secure' : endpoint.cert is not None,
-                    'api_name'  : 'default',
-                    },
-                'fixtures' : {},
-                's3 main'  : {},
-                's3 alt'   : {},
-               's3 tenant': {},
-                'iam'      : {},
-                }
-            )
+
+    for client, client_config in config.items():
+        if 'sts_tests' in client_config:
+            ctx.sts_variable = True
+        else:
+            ctx.sts_variable = False
+        #This will be the structure of config file when you want to run webidentity_test (sts-test)
+        if ctx.sts_variable and "TOKEN" in os.environ:
+            for client in clients:
+                endpoint = ctx.rgw.role_endpoints.get(client)
+                assert endpoint, 's3tests: no rgw endpoint for {}'.format(client)
+
+                s3tests_conf[client] = ConfigObj(
+                    indent_type='',
+                    infile={
+                        'DEFAULT':
+                            {
+                            'port'      : endpoint.port,
+                            'is_secure' : endpoint.cert is not None,
+                            'api_name'  : 'default',
+                            },
+                        'fixtures'   : {},
+                        's3 main'    : {},
+                        's3 alt'     : {},
+                        's3 tenant'  : {},
+                        'iam'        : {},
+                        'webidentity': {},
+                    }
+                )
+
+        elif ctx.sts_variable:
+            #This will be the structure of config file when you want to run assume_role_test and get_session_token_test (sts-test)
+            for client in clients:
+                endpoint = ctx.rgw.role_endpoints.get(client)
+                assert endpoint, 's3tests: no rgw endpoint for {}'.format(client)
+
+                s3tests_conf[client] = ConfigObj(
+                    indent_type='',
+                    infile={
+                        'DEFAULT':
+                            {
+                            'port'      : endpoint.port,
+                            'is_secure' : endpoint.cert is not None,
+                            'api_name'  : 'default',
+                            },
+                        'fixtures'   : {},
+                        's3 main'    : {},
+                        's3 alt'     : {},
+                        's3 tenant'  : {},
+                        'iam'        : {},
+                        }
+                    ) 
+
+        else:
+            #This will be the structure of config file when you want to run normal s3-tests
+            for client in clients:
+                endpoint = ctx.rgw.role_endpoints.get(client)
+                assert endpoint, 's3tests: no rgw endpoint for {}'.format(client)
+
+                s3tests_conf[client] = ConfigObj(
+                    indent_type='',
+                    infile={
+                        'DEFAULT':
+                            {
+                            'port'      : endpoint.port,
+                            'is_secure' : endpoint.cert is not None,
+                            'api_name'  : 'default',
+                            },
+                        'fixtures'   : {},
+                        's3 main'    : {},
+                        's3 alt'     : {},
+                        's3 tenant'  : {},
+                        }
+                    )
 
     with contextutil.nested(
         lambda: download(ctx=ctx, config=config),