Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 74 additions & 5 deletions barbican/cmd/barbican_manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@

from oslo_config import cfg
from oslo_log import log as logging
# from oslo_config import cfg as oslo_cfg

from sqlalchemy import create_engine, text
from sqlalchemy import create_engine
from sqlalchemy import text

from barbican.cmd.hsm_partition_create import create_hsm_partition
from barbican.cmd import pkcs11_kek_rewrap as pkcs11_rewrap
from barbican.common import config
from barbican.model import clean
Expand Down Expand Up @@ -98,7 +98,7 @@ class DbCommands(object):
action="store_true",
dest="do_clean_unassociated_projects",
default=False,
help="Remove projects that have no " "associated resources.",
help="Remove projects that have no associated resources.",
)
@args(
"--soft-delete-expired-secrets",
Expand Down Expand Up @@ -617,7 +617,6 @@ def _verify_label_does_not_exist(self, key_type, label, session):


class SAPCommands(object):

description = (
"Move all secrets associated with "
"the old_project_id to the new_project_id."
Expand Down Expand Up @@ -687,6 +686,76 @@ def move_secrets(
except Exception as e:
print(f"An error occurred: {e}")

@args(
"--external-project-id",
"-p",
dest="external_project_id",
metavar="<external-project-id>",
help="External project ID",
)
@args(
"--partition-label",
"-l",
dest="partition_label",
metavar="<partition-label>",
help="Label for the HSM partition",
)
@args(
"--token-label",
"-t",
dest="token_label",
metavar="<token-label>",
help="Token label",
)
@args(
"--slot-id",
"-s",
dest="slot_id",
type=int,
metavar="<slot-id>",
help="Slot ID for the HSM",
)
@args(
"--password",
dest="password",
metavar="<password>",
help="Password/PIN for the HSM",
)
@args(
"--partition-id",
dest="partition_id",
metavar="<partition-id>",
help="Override partition UUID",
)
@args(
"--debug",
dest="debug",
action="store_true",
default=False,
help="Enable debug output",
)
def create_hsm_partition_config(
self,
conf,
external_project_id=None,
partition_label=None,
token_label=None,
slot_id=None,
password=None,
partition_id=None,
debug=False,
):
parsed_args = argparse.Namespace(
external_project_id=external_project_id,
token_label=token_label,
slot_id=slot_id,
password=password,
partition_id=partition_id,
partition_label=partition_label,
debug=debug,
)
create_hsm_partition(parsed_args)


CATEGORIES = {
"db": DbCommands,
Expand Down
182 changes: 47 additions & 135 deletions barbican/cmd/hsm_partition_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,159 +18,81 @@
and mapping them to projects in the Barbican database.
"""

import argparse
import sys
import uuid

from oslo_utils import timeutils

from barbican.common import resources
from barbican.common import utils
from barbican.model import models
from barbican.model import repositories

DEFAULT_CREDS = {
"library_path": "/usr/local/lib/softhsm/libsofthsm2.so",
"password": "1234",
}

# Initialize logging and configuration
CONF = repositories.CONF
LOG = utils.getLogger(__name__)


# Set up command-line arguments
def main():
parser = argparse.ArgumentParser(
description="Create HSM partition configurations in Barbican."
)

parser.add_argument(
"--external-project-id",
"-p",
help="External project ID",
default="12345",
)
parser.add_argument(
"--partition-label",
"-l",
help="Label for the HSM partition",
default="hsm-partition-1",
)
parser.add_argument(
"--token-label", "-t", help="Token label", default="testing"
)
parser.add_argument(
"--slot-id",
"-s",
help="Slot ID for the HSM",
type=int,
default=175517174,
)
parser.add_argument(
"--library-path",
help="Path to the HSM library",
# I'm testing against softhsm2
default="/usr/local/lib/softhsm/libsofthsm2.so",
)
parser.add_argument(
"--password", help="Password/PIN for the HSM", default="1234"
)
parser.add_argument(
"--partition-id",
help="Override partition UUID (default: auto-generated)",
default=None,
)
parser.add_argument(
"--mapping-id",
help="Override mapping UUID (default: auto-generated)",
default=None,
)
parser.add_argument(
"--debug", help="Enable debug output", action="store_true"
)

args = parser.parse_args()

if args.debug:
LOG.logger.setLevel("DEBUG")

try:
setup_database()
create_hsm_partition(args)
LOG.info("HSM partition configuration created successfully")
except Exception as e:
LOG.exception("Error creating HSM partition configuration: %s", e)
return 1

return 0


def setup_database():
def _setup_database():
"""Initialize database connection."""
LOG.debug("Initializing database connection")
repositories.setup_database_engine_and_factory()
repositories.start()


def create_hsm_partition(args):
if hasattr(args, "debug") and args.debug:
LOG.logger.setLevel("DEBUG")

_setup_database()

"""Create HSM partition configuration and map to project."""

# Initialize session
session = repositories.get_session()
# Step 1: Fetch or create project based on external_id
project = resources.get_or_create_project(args.external_project_id)
LOG.debug("Got project with id: %s", project.id)

try:
# Step 1: Check for existing external_id conflict
project_query = session.query(models.Project).filter_by(
external_id=args.external_project_id, deleted=False
# Step 2: Check if HSM partition config already exists for the project
hsm_partition_config_repo = (
repositories.get_hsm_partition_config_repository()
)
existing_config = hsm_partition_config_repo.get_by_project_id(
project.id, suppress_exception=True
)

if existing_config:
LOG.info(
"HSM partition config already exists for project %s",
project.external_project_id,
)
return existing_config

# Step 3: Create new HSM partition config for the project
hsm_partition_config_obj = models.HSMPartitionConfig()
# Always set the id explicitly for HSMPartitionConfig
hsm_partition_config_obj.id = args.partition_id or str(uuid.uuid4())
hsm_partition_config_obj.created_at = timeutils.utcnow()
hsm_partition_config_obj.updated_at = timeutils.utcnow()
hsm_partition_config_obj.project_id = project.id
hsm_partition_config_obj.partition_label = args.partition_label or ""
hsm_partition_config_obj.token_label = args.token_label
hsm_partition_config_obj.slot_id = args.slot_id
hsm_partition_config_obj.credentials = {"password": args.password}
hsm_partition_config_obj.status = models.States.ACTIVE
hsm_partition_config_obj.deleted = False

project = project_query.first()
if project:
LOG.warning(
"Project (external_id: %s) already exists!",
args.external_project_id,
)
else:
# Create project
LOG.debug("Project doesn't exist, creating new one")
project = models.Project()
project.external_id = args.external_project_id
project.status = models.States.ACTIVE
project.deleted = False
session.add(project)
session.flush()
LOG.debug("Created new project with id: %s", project.id)

# Step: Create HSM partition config
LOG.debug("Creating HSM partition config")
hsm_partition_config = models.HSMPartitionConfig()

# Always set the id explicitly for HSMPartitionConfig
hsm_partition_config.id = args.partition_id or str(uuid.uuid4())
hsm_partition_config.created_at = timeutils.utcnow()
hsm_partition_config.updated_at = timeutils.utcnow()
hsm_partition_config.project_id = project.id
hsm_partition_config.partition_label = args.partition_label
hsm_partition_config.token_label = args.token_label
hsm_partition_config.slot_id = args.slot_id

# Set credentials
hsm_partition_config.credentials = {
"library_path": args.library_path,
"password": args.password,
}
hsm_partition_config.status = models.States.ACTIVE
hsm_partition_config.deleted = False

session.add(hsm_partition_config)
session.flush() # This will assign an ID to the partition if needed
try:
hsm_partition_config = hsm_partition_config_repo.create_from(
hsm_partition_config_obj
)
repositories.commit()
except Exception:
repositories.rollback()
return None
else:
LOG.debug(
"Created HSM partition config with id: %s", hsm_partition_config.id
)

# Commit all changes
session.commit()

LOG.info("Successfully created HSM partition configuration:")
LOG.info(
" Project ID: %s (External ID: %s)",
Expand All @@ -182,14 +104,4 @@ def create_hsm_partition(args):
hsm_partition_config.id,
args.partition_label,
)

except Exception as e:
LOG.exception("Error creating HSM partition configuration: %s", e)
session.rollback()
raise
finally:
session.close()


if __name__ == "__main__":
sys.exit(main())
return hsm_partition_config
1 change: 0 additions & 1 deletion barbican/integrationtests/plugin/test_resource_softhsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ def _create_project_secret_store_mapping(
project = resources.get_or_create_project(project_name)

# Create HSM partition config in DB
# ToDo: Refactor in a proper way with repository
# ToDo: Note: Some of the options are not present in HSM crypto plugin
args = Namespace(
external_project_id=project.external_id,
Expand Down
34 changes: 34 additions & 0 deletions barbican/model/repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -2590,6 +2590,40 @@ def _do_build_get_query(self, entity_id, external_project_id, session):
"""Sub-class hook: build a retrieve query."""
return session.query(models.HSMPartitionConfig).filter_by(id=entity_id)

def create_from(self, entity, session=None):
"""Sub-class hook: create from entity."""
if not entity:
msg = u._("Must supply non-None {entity_name}.").format(
entity_name=self._do_entity_name()
)
raise exception.Invalid(msg)

LOG.debug("Begin create from...")
session = self.get_session(session)
start = time.time() # DEBUG

# Validate the attributes before we go any further. From my
# (unknown Glance developer) investigation, the @validates
# decorator does not validate
# on new records, only on existing records, which is, well,
# idiotic.
self._do_validate(entity.to_dict())

try:
LOG.debug("Saving entity...")
entity.save(session=session)
except db_exc.DBDuplicateEntry as e:
session.rollback()
LOG.exception("Problem saving entity for create")
error_msg = re.sub("[()]", "", str(e.args))
raise exception.ConstraintCheck(error=error_msg)

LOG.debug(
"Elapsed repo " "create secret:%s", (time.time() - start)
) # DEBUG

return entity

def get_by_project_id(
self, project_id, suppress_exception=False, session=None
):
Expand Down
5 changes: 2 additions & 3 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,11 @@ pkcs11-tool --module /usr/local/lib/softhsm/libsofthsm2.so -O \
Create HSM partition config for the project in the DB:

```
python ./barbican/cmd/hsm_partition_create.py \
barbican-manage sap create_hsm_partition_config \
--external-project-id <project_name> \
--token-label <label> \
--slot-id <slot_id> \
--password <crypto_user_pin> \
--library-path /usr/local/lib/softhsm/libsofthsm2.so
--password <crypto_user_pin>
```

## Run Unit Tests
Expand Down