Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6175588

Browse files
DirectXMan12frozencemetery
authored andcommitted
Docs: Add in the basic tutorial
This commit adds the basic tutorial to the documentation. It is converted into a Sphinx-readable (docutils) format using the `recommonmark` package.
1 parent 691e288 commit 6175588

File tree

7 files changed

+249
-1
lines changed

7 files changed

+249
-1
lines changed

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ docs/build
1414
__dont_use_cython__.txt
1515
**/__pycache__
1616
.eggs
17+
.venv

‎docs-requirements.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
Sphinx >= 1.3.1
22
sphinx-rtd-theme >= 0.1.9
33
sphinxcontrib-napoleon >= 0.2.8
4+
recommonmark >= 0.4.0
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from recommonmark.parser import CommonMarkParser
2+
from docutils import nodes
3+
4+
# treats "verbatim" (code without a language specified) as a code sample
5+
class AllCodeCommonMarkParser(CommonMarkParser):
6+
def verbatim(self, text):
7+
node = nodes.literal_block(text, text)
8+
self.current_node.append(node)

‎docs/source/basic-tutorial.md‎

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
A Basic Introduction to GSSAPI
2+
==============================
3+
4+
GSSAPI (which stands for "Generic Security Service API") is an
5+
standard layer for interfacing with security services. While it
6+
supports multiple different mechanisms, it is most commonly used
7+
with Kerberos 5 ("krb5" for short).
8+
9+
This tutorial will provide a basic introduction to interacting with
10+
GSSAPI through Python.
11+
12+
*Note*: This file is designed to be runnable using
13+
[YALPT](https://github.com/directxman12/yalpt). You can also just
14+
read it normally.
15+
16+
To start out, we'll import python-gssapi, and save the current FQDN
17+
for later:
18+
19+
>>> import gssapi, socket
20+
>>> FQDN = socket.getfqdn()
21+
>>>
22+
23+
Note that this assumes you have a KRB5 realm set up, and some relevant
24+
functions available in the `REALM` object (see gssapi-console.py, or
25+
try `$ run-lit -e gssapi basic-tutorial.md` when you have both
26+
gssapi-console and yalpt installed). Any actions performed using the
27+
`REALM` object are not part of the GSSAPI library; the `REALM` object
28+
simply contians wrappers to krb5 commands generally run separately from
29+
the application using GSSAPI.
30+
31+
Names and Credentials
32+
---------------------
33+
34+
Two important concepts in GSSAPI are *names* and *credentials*.
35+
36+
*Names*, as the name suggests, identify different entities, be they
37+
users or services. GSSAPI has the concept of different *name types*.
38+
These represent different types of names and corresponding sytaxes
39+
for representing names as strings.
40+
41+
Suppose we wanted to refer to an HTTP server on the current host.
42+
We could refer to it as a *host-based service*, or in the default
43+
mechanism form (in this case, for krb5):
44+
45+
>>> server_hostbased_name = gssapi.Name('http@' + FQDN, name_type=gssapi.NameType.hostbased_service)
46+
>>> server_hostbased_name
47+
Name(b'http@sross', <OID 1.2.840.113554.1.2.1.4>)
48+
>>> server_name = gssapi.Name('http/sross@')
49+
>>> server_name
50+
Name(b'http/sross@', None)
51+
>>>
52+
53+
These are both effectively the same, but if we *canonicalize* both
54+
names with respect to krb5, we'll see that GSSAPI knows they're the
55+
same:
56+
57+
>>> server_name == server_hostbased_name
58+
False
59+
>>> server_canon_name = server_name.canonicalize(gssapi.MechType.kerberos)
60+
>>> server_hostbased_canon_name = server_hostbased_name.canonicalize(gssapi.MechType.kerberos)
61+
>>> server_canon_name == server_hostbased_canon_name
62+
True
63+
>>>
64+
65+
To compare two names of different name types, you should canonicalize
66+
them first.
67+
68+
*Credentials* represent identification for a user or service. In
69+
order to establish secure communication with other entities, a user
70+
or service first needs credentials. For the krb5 mechanism,
71+
credentials generally represent a handle to the TGT.
72+
73+
Credentials may be acquired for a particular name, or the default set
74+
of credentials may be acquired.
75+
76+
For instance, suppose that we are writing a server, and wish to
77+
communicate accept connections as the 'http' service. We would need
78+
to acquire credentials as such:
79+
80+
>>> REALM.addprinc('http/%s@%s' % (FQDN, REALM.realm))
81+
>>> REALM.extract_keytab('http/%s@%s' % (FQDN, REALM.realm), REALM.keytab)
82+
>>> server_creds = gssapi.Credentials(usage='accept', name=server_name)
83+
>>>
84+
85+
Note that for the krb5 mechanism, in order to acquire credentials with
86+
the GSSAPI, the system must already have a way to access those credentials.
87+
For users, this generally means that they have already performed a `kinit`
88+
(i.e. have cached a TGT), while for services (like above), having a keytab
89+
is sufficient. This process is generally performed outside the application
90+
using the GSSAPI.
91+
92+
Credentials have a *usage*: 'accept' for accepting security contexts,
93+
'initiate' for initiating security contexts, or 'both' for
94+
credentials used for both initiating and accepting security contexts.
95+
96+
Credentials also have an associated *name*, *lifetime* (which may
97+
be `None` for indefinite), and set of *mechansims* with which the
98+
credentials are usable:
99+
100+
>>> server_creds.usage
101+
'accept'
102+
>>> server_creds.name == server_name
103+
True
104+
>>> server_creds.lifetime is None
105+
True
106+
>>> gssapi.MechType.kerberos in server_creds.mechs
107+
True
108+
>>> gssapi.MechType.kerberos in server_creds.mechs
109+
True
110+
>>>
111+
112+
Each of these settings is setable from the constructor as `usage`,
113+
`name`, `lifetime`, and `mechs`.
114+
115+
Security Contexts
116+
-----------------
117+
118+
*Security contexts* represent active sessions between two different
119+
entities. Security contexts are used to verify identities, as well
120+
as ensure *integrity* (message signing), *confidentiality* (message
121+
encryption), or both for messages exchanged between the two parties.
122+
123+
When establishing a security context, the default credentials are
124+
used unless otherwise specified. This allows applications to use
125+
the user's already acquired credentials:
126+
127+
>>> client_ctx = gssapi.SecurityContext(name=server_name, usage='initiate')
128+
>>> initial_client_token = client_ctx.step()
129+
>>> client_ctx.complete
130+
False
131+
>>>
132+
133+
Just like credentials, security contexts are either initiating
134+
contexts, or accepting contexts (they cannot be both). Initating
135+
contexts must specify at least a target name. In this case,
136+
we indicate that we wish to establish a context with the HTTP server
137+
from above. The http server can then accept that context:
138+
139+
>>> server_ctx = gssapi.SecurityContext(creds=server_creds, usage='accept')
140+
>>> initial_server_token = server_ctx.step(initial_client_token)
141+
>>>
142+
143+
As you can see, creating an accepting security context is similar.
144+
Here, we specify a set of accepting credentials to use, although
145+
this is optional (the defaults will be used if no credentials are
146+
specified).
147+
148+
Let's finish up the exchange:
149+
150+
>>> server_tok = initial_server_token
151+
>>>
152+
>>> while not (client_ctx.complete and server_ctx.complete):
153+
... client_tok = client_ctx.step(server_tok)
154+
... if not client_tok:
155+
... break
156+
... server_tok = server_ctx.step(client_tok)
157+
...
158+
>>> client_ctx.complete and server_ctx.complete
159+
True
160+
>>>
161+
162+
We can now wrap and unwrap messages, using the `wrap` and `unwrap` methods
163+
on `SecurityContext`:
164+
165+
>>> message = b'some message here'
166+
>>> wrapped_message, msg_encrypted = client_ctx.wrap(message, True)
167+
>>> message not in wrapped_message
168+
True
169+
>>> msg_encrypted
170+
True
171+
>>> server_ctx.unwrap(wrapped_message)
172+
UnwrapResult(message=b'some message here', encrypted=True, qop=0)
173+
>>>
174+
175+
We can use the second parameter to control whether or not we encrypt the
176+
messages, or just sign them:
177+
178+
>>> signed_message, msg_encrypted = client_ctx.wrap(message, False)
179+
>>> msg_encrypted
180+
False
181+
>>> message in signed_message
182+
True
183+
>>> server_ctx.unwrap(signed_message)
184+
UnwrapResult(message=b'some message here', encrypted=False, qop=0)
185+
>>>
186+
187+
Manually passing in a second parameter and checking whether or not encryption
188+
was used can get tedious, so python-gssapi provides two convinience methods
189+
to help with this: `encrypt` and `decrypt`. If the context is set up to use
190+
encryption, they will call `wrap` with encryption. If not, they will
191+
call `wrap` without encryption.
192+
193+
>>> encrypted_message = client_ctx.encrypt(message)
194+
>>> encrypted_message != message
195+
True
196+
>>> server_ctx.decrypt(encrypted_message)
197+
b'some message here'
198+
>>>
199+
200+
Notice that if we try to use `decrypt` a signed message, and exception will be raised,
201+
since the context was set up to use encryption (the default):
202+
203+
>>> signed_message, _ = client_ctx.wrap(message, False)
204+
>>> server_ctx.decrypt(signed_message)
205+
Traceback (most recent call last):
206+
File "<stdin>", line 1, in <module>
207+
File "<string>", line 2, in decrypt
208+
File "/home/directxman12/dev/gssapi/gssapi-console/.venv/lib/python3.4/site-packages/gssapi/_utils.py", line 167, in check_last_err
209+
return func(self, *args, **kwargs)
210+
File "/home/directxman12/dev/gssapi/gssapi-console/.venv/lib/python3.4/site-packages/gssapi/sec_contexts.py", line 295, in decrypt
211+
unwrapped_message=res.message)
212+
gssapi.exceptions.EncryptionNotUsed: Confidentiality was requested, but not used: The context was established with encryption, but unwrapped message was not encrypted.
213+
>>>
214+
215+
There you have it: the basics of GSSAPI. You can use the `help` function
216+
at the interpreter, or check the [docs](http://pythonhosted.org/gssapi/)
217+
for more information.

‎docs/source/conf.py‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
sys.path.insert(0, os.path.abspath('../..'))
2222
sys.path.insert(0, os.path.abspath('../custom_extensions'))
2323

24+
from custom_recommonmark import AllCodeCommonMarkParser
25+
2426
# -- General configuration -----------------------------------------------------
2527

2628
# If your documentation needs a minimal Sphinx version, state it here.
@@ -33,8 +35,13 @@
3335
# Add any paths that contain templates here, relative to this directory.
3436
templates_path = ['_templates']
3537

38+
# Parsers for different suffixes
39+
source_parsers = {
40+
'.md': AllCodeCommonMarkParser
41+
}
42+
3643
# The suffix of source filenames.
37-
source_suffix = '.rst'
44+
source_suffix = ['.rst', '.md']
3845

3946
# The encoding of source files.
4047
#source_encoding = 'utf-8-sig'

‎docs/source/index.rst‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@ corresponding C functions. The high-level API makes use of the low-level API
1919
to access underlying GSSAPI functionality. Additionally certain extensions
2020
are currently only available from the low-level API.
2121

22+
To get started, check out the :doc:`tutorials page <tutorials>` or jump
23+
straight into the :doc:`high-level API documentation <gssapi>`.
24+
2225
.. toctree::
2326
:hidden:
2427
:maxdepth: 3
2528

2629
gssapi.rst
2730
gssapi.raw.rst
31+
tutorials.rst
2832

2933

3034
Indices and tables

‎docs/source/tutorials.rst‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Tutorials
2+
=========
3+
4+
To get started with using Python-GSSAPI, check out some of the following tutorials:
5+
6+
.. toctree::
7+
:maxdepth: 1
8+
9+
basic-tutorial.md
10+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /