Skip to content

Commit

Permalink
Migrate to click framework
Browse files Browse the repository at this point in the history
The click framework is a new framework for command line
interfaces. We use a file for each command in
the commands/ directory to keep things easier to manage.

We add a new command section "certificate" - although it
is a tokentype, but this makes creating certificates, CSRs...
easier.

Closes #45
Closes #44
  • Loading branch information
cornelinux committed Apr 14, 2020
1 parent c92f510 commit 255ed18
Show file tree
Hide file tree
Showing 13 changed files with 1,580 additions and 1,507 deletions.
4 changes: 4 additions & 0 deletions privacyideautils/clientutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
import pprint
import requests
import gettext
from requests.packages.urllib3.exceptions import InsecureRequestWarning

_ = gettext.gettext

__version__ = 3.0
TIMEOUT = 5
etng = False

Expand Down Expand Up @@ -90,6 +92,8 @@ def __init__(self, username, password, baseuri="http://localhost:5000",
self.baseuri = baseuri
self.log = logging.getLogger('privacyideaclient')
self.verify_ssl = not no_ssl_check
if not self.verify_ssl:
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
# Do the first server communication and retrieve the auth token
self.set_credentials(username, password)

Expand Down
Empty file.
69 changes: 69 additions & 0 deletions privacyideautils/commands/audit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
#
# 2020-04-13 Cornelius Kölbel <[email protected]>
# migrate to click
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
# License as published by the Free Software Foundation; either
# version 3 of the License, or any later version.
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import click
import datetime
import logging
from privacyideautils.clientutils import (showresult,
dumpresult,
privacyideaclient,
__version__)

@click.group()
@click.pass_context
def audit(ctx):
"""
Manage the audit log. Basically fetch audit information.
"""
pass

@audit.command()
@click.pass_context
@click.option("--page", help="The page number to view", type=int)
@click.option("--rp", help="The number of entries per page", type=int)
@click.option("--sortname", help="The name of the column to sort by", default="number")
@click.option("--sortorder", help="The order to sort (desc, asc)",
type=click.Choice(["desc", "asc"]), default="desc")
@click.option("--query", help="A search tearm to search for")
@click.option("--qtype", help="The column to search for")
def list(ctx, page, rp, sortname, sortorder, query, qtype):
"""
List the audit log
"""
client = ctx.obj["pi_client"]
param = {}
if page:
param["page"] = page
if rp:
param["rp"] = rp
if sortname:
param["sortname"] = sortname
if sortorder:
param["sortorder"] = sortorder
if query:
param["query"] = query
if qtype:
param["qtype"] = qtype
resp = client.auditsearch(param)
r1 = resp.data
auditdata = r1.get("result").get("value").get("auditdata")
count = r1.get("result").get("value").get("count")
for row in auditdata:
print(row)
print("Total: {0!s}".format(count))

103 changes: 103 additions & 0 deletions privacyideautils/commands/certificate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
#
# 2020-04-13 Cornelius Kölbel <[email protected]>
# migrate to click
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
# License as published by the Free Software Foundation; either
# version 3 of the License, or any later version.
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import click
import datetime
import logging
from privacyideautils.clientutils import (showresult,
dumpresult,
privacyideaclient,
__version__)
from privacyideautils.clientutils import PrivacyIDEAClientError

@click.group()
@click.pass_context
def certificate(ctx):
"""
Manage certificates
"""
pass


@certificate.command()
@click.pass_context
@click.option("--ca", help="Specify the CA where you want to send the CSR to.")
@click.option("--user", help="The user to whom the certificate should be assigned.")
@click.option("--realm", help="The realm of the user to whom the certificate should be assigned.")
@click.argument("requestfile", type=click.File("rb"))
def sign(ctx, requestfile, ca, user, realm):
"""
Send a certificate signing request to privacyIDEA and have the CSR signed.
"""
client = ctx.obj["pi_client"]
param = {"type": "certificate",
"genkey": 1}
if requestfile:
param["request"] = requestfile.read()
if ca:
param["ca"] = ca
if user:
param["user"] = user
if realm:
param["realm"] = realm

try:
resp = client.inittoken(param)
print("result: {0!s}".format(resp.status))
showresult(resp.data)
if resp.status == 200:
if not param.get("serial"):
print("serial: {0!s}".format(resp.data.get("detail", {}).get("serial")))
except PrivacyIDEAClientError as e:
print(e)


@certificate.command()
@click.pass_context
@click.option("--ca", help="Specify the CA where you want to send the CSR to.")
@click.option("--user", help="The user to whom the certificate should be assigned.")
@click.option("--realm", help="The realm of the user to whom the certificate should be assigned.")
@click.option("--pin", help="Set the PIN of the PKCS12 file.")
@click.option("--template", help="Use the specified template.")
def create(ctx, ca, user, realm, pin, template):
"""
Create a key pair and certificate on the server side.
"""
client = ctx.obj["pi_client"]
param = {"type": "certificate",
"genkey": 1}
if template:
param["request"] = requestfile.read()
if ca:
param["ca"] = ca
if user:
param["user"] = user
if realm:
param["realm"] = realm
if pin:
param["pin"] = pin

try:
resp = client.inittoken(param)
print("result: {0!s}".format(resp.status))
showresult(resp.data)
if resp.status == 200:
if not param.get("serial"):
print("serial: {0!s}".format(resp.data.get("detail", {}).get("serial")))
except PrivacyIDEAClientError as e:
print(e)
75 changes: 75 additions & 0 deletions privacyideautils/commands/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
#
# 2020-04-13 Cornelius Kölbel <[email protected]>
# migrate to click
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
# License as published by the Free Software Foundation; either
# version 3 of the License, or any later version.
#
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import click
import datetime
import logging
from privacyideautils.clientutils import (showresult,
dumpresult,
privacyideaclient,
__version__)

@click.group()
@click.pass_context
def config(ctx):
"""
Manage the configuration.
"""
pass


@config.command()
@click.pass_context
def list(ctx):
"""
List the configuration of the privacyIDEA server.
"""
client = ctx.obj["pi_client"]
response = client.getconfig({})
showresult(response.data)


@config.command()
@click.pass_context
@click.option('--config', required=True, multiple=True,
help="Set a configuration value. Use it like --config key=value.")
def set(ctx, config):
"""
Set configuration values of privacyIDEA.
"""
client = ctx.obj["pi_client"]
for conf in config:
param = {}
(k, v) = conf.split("=")
param[k] = v
response = client.setconfig(param)
showresult(response.data)


@config.command()
@click.pass_context
@click.option('--key', required=True, multiple=True,
help="Delete config values from the privacyIDEA server by key.")
def delete(ctx, key):
"""
Delete a configuration value from the privacyIDEA server.
"""
client = ctx.obj["pi_client"]
for k in key:
response = client.deleteconfig(k)
showresult(response.data)
Loading

0 comments on commit 255ed18

Please sign in to comment.