~soren/nova/iptables-security-groups

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/doc/core/howto/cred.html

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html  PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
 
2
  <head>
 
3
<title>Twisted Documentation: Cred: Pluggable Authentication</title>
 
4
<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
 
5
  </head>
 
6
 
 
7
  <body bgcolor="white">
 
8
    <h1 class="title">Cred: Pluggable Authentication</h1>
 
9
    <div class="toc"><ol><li><a href="#auto0">Goals</a></li><li><a href="#auto1">Cred objects</a></li><ul><li><a href="#auto2">The Portal</a></li><li><a href="#auto3">The CredentialChecker</a></li><li><a href="#auto4">The Credentials</a></li><li><a href="#auto5">The Realm</a></li><li><a href="#auto6">The Avatar</a></li><li><a href="#auto7">The Mind</a></li></ul><li><a href="#auto8">Responsibilities</a></li><ul><li><a href="#auto9">Server protocol implementation</a></li><li><a href="#auto10">Application implementation</a></li><li><a href="#auto11">Deployment</a></li></ul><li><a href="#auto12">Cred plugins</a></li><ul><li><a href="#auto13">Authentication with cred plugins</a></li><li><a href="#auto14">Building a cred plugin</a></li></ul><li><a href="#auto15">Conclusion</a></li></ol></div>
 
10
    <div class="content">
 
11
    <span/>
 
12
 
 
13
    <h2>Goals<a name="auto0"/></h2>
 
14
 
 
15
<p>Cred is a pluggable authentication system for servers.  It allows any
 
16
number of network protocols to connect and authenticate to a system, and
 
17
communicate to those aspects of the system which are meaningful to the specific
 
18
protocol.  For example, Twisted's POP3 support passes a <q>username and
 
19
password</q> set of credentials to get back a mailbox for the specified email
 
20
account.  IMAP does the same, but retrieves a slightly different view of the
 
21
same mailbox, enabling those features specific to IMAP which are not available
 
22
in other mail protocols.</p>
 
23
 
 
24
<p>Cred is designed to allow both the backend implementation of the business
 
25
logic - called the <em>avatar</em> - and the authentication database - called
 
26
the <em>credential checker</em> - to be decided during deployment. For example,
 
27
the same POP3 server should be able to authenticate against the local UNIX
 
28
password database or an LDAP server without having to know anything about how
 
29
or where mail is stored.  </p>
 
30
 
 
31
<p>To sketch out how this works - a <q>Realm</q> corresponds to an application
 
32
domain and is in charge of avatars, which are network-accessible business logic
 
33
objects.  To connect this to an authentication database, a top-level object
 
34
called a <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.portal.Portal.html" title="twisted.cred.portal.Portal">Portal</a></code> stores a
 
35
realm, and a number of credential checkers.  Something that wishes to log in,
 
36
such as a <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.protocol.Protocol.html" title="twisted.internet.protocol.Protocol">Protocol</a></code>,
 
37
stores a reference to the portal. Login consists of passing credentials and a
 
38
request interface (e.g. POP3's <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.protocols.pop3.IMailbox.html" title="twisted.protocols.pop3.IMailbox">IMailbox</a></code>) to the portal. The portal passes
 
39
the credentials to the appropriate credential checker, which returns an avatar
 
40
ID. The ID is passed to the realm, which returns the appropriate avatar.  For a
 
41
Portal that has a realm that creates mailbox objects and a credential checker
 
42
that checks /etc/passwd, login consists of passing in a username/password and
 
43
the IMailbox interface to the portal. The portal passes this to the /etc/passwd
 
44
credential checker, gets back a avatar ID corresponding to an email account,
 
45
passes that to the realm and gets back a mailbox object for that email
 
46
account.</p>
 
47
 
 
48
<p>Putting all this together, here's how a login request will typically be
 
49
processed:</p>
 
50
 
 
51
<img src="../img/cred-login.png" title="Cred Login"/>
 
52
 
 
53
    <h2>Cred objects<a name="auto1"/></h2>
 
54
    <h3>The Portal<a name="auto2"/></h3>
 
55
<p>This is the the core of login, the point of integration between all the objects
 
56
in the cred system.  There is one
 
57
concrete implementation of Portal, and no interface - it does a very
 
58
simple task.  A <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.portal.Portal.html" title="twisted.cred.portal.Portal">Portal</a></code>
 
59
associates one (1) Realm with a collection of
 
60
CredentialChecker instances.  (More on those later.)</p>
 
61
 
 
62
<p>If you are writing a protocol that needs to authenticate against
 
63
something, you will need a reference to a Portal, and to nothing else.
 
64
This has only 2 methods -</p>
 
65
 
 
66
<ul>
 
67
<li><code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.portal.Portal.login.html" title="twisted.cred.portal.Portal.login">login</a></code><code>(credentials, mind, *interfaces)</code>
 
68
 
 
69
<p>The docstring is quite expansive (see <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.portal.html" title="twisted.cred.portal">twisted.cred.portal</a></code>), but in
 
70
brief, this is what you call when you need to call in order to connect
 
71
a user to the system.  Typically you only pass in one interface, and the mind is
 
72
<code class="python">None</code>. The interfaces are the possible interfaces the returned
 
73
avatar is expected to implement, in order of preference.
 
74
The result is a deferred which fires a tuple of:</p>
 
75
    <ul>
 
76
        <li>interface the avatar implements (which was one of the interfaces passed in the *interfaces
 
77
tuple)</li>
 
78
        <li>an object that implements that interface (an avatar)</li>
 
79
    <li>logout, a 0-argument callable which disconnects the connection that was
 
80
established by this call to login</li>
 
81
    </ul>
 
82
<p>The logout method has to be called when the avatar is logged out. For POP3 this means
 
83
when the protocol is disconnected or logged out, etc..</p>
 
84
</li>
 
85
<li><code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.portal.Portal.registerChecker.html" title="twisted.cred.portal.Portal.registerChecker">registerChecker</a></code><code>(checker, *credentialInterfaces)</code>
 
86
 
 
87
<p>which adds a CredentialChecker to the portal. The optional list of interfaces are interfaces of credentials
 
88
that the checker is able to check.</p>
 
89
</li></ul>
 
90
 
 
91
    <h3>The CredentialChecker<a name="auto3"/></h3>
 
92
 
 
93
<p>This is an object implementing <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.checkers.ICredentialsChecker.html" title="twisted.cred.checkers.ICredentialsChecker">ICredentialsChecker</a></code> which resolves some
 
94
credentials to an avatar ID.
 
95
 
 
96
Whether the credentials are stored in an in-memory data structure, an
 
97
Apache-style htaccess file, a UNIX password database, an SSH key database,
 
98
or any other form, an implementation of <code>ICredentialsChecker</code> is
 
99
how this data is connected to cred.
 
100
 
 
101
A credential checker
 
102
stipulates some requirements of the credentials it can check by
 
103
specifying a credentialInterfaces attribute, which is a list of
 
104
interfaces.  Credentials passed to its requestAvatarId method must
 
105
implement one of those interfaces.</p>
 
106
 
 
107
<p>For the most part, these things will just check usernames and passwords
 
108
and produce the username as the result, but hopefully we will be seeing
 
109
some public-key, challenge-response, and certificate based credential
 
110
checker mechanisms soon.</p>
 
111
 
 
112
<p>A credential checker should raise an error if it cannot authenticate
 
113
the user, and return <code>twisted.cred.checkers.ANONYMOUS</code>
 
114
for anonymous access.</p>
 
115
 
 
116
    <h3>The Credentials<a name="auto4"/></h3>
 
117
<p>Oddly enough, this represents some credentials that the user presents.
 
118
Usually this will just be a small static blob of data, but in some
 
119
cases it will actually be an object connected to a network protocol.
 
120
For example, a username/password pair is static, but a
 
121
challenge/response server is an active state-machine that will require
 
122
several method calls in order to determine a result.</p>
 
123
 
 
124
<p>Twisted comes with a number of credentials interfaces and implementations
 
125
in the <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.credentials.html" title="twisted.cred.credentials">twisted.cred.credentials</a></code> module,
 
126
such as <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.credentials.IUsernamePassword.html" title="twisted.cred.credentials.IUsernamePassword">IUsernamePassword</a></code>
 
127
and <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.credentials.IUsernameHashedPassword.html" title="twisted.cred.credentials.IUsernameHashedPassword">IUsernameHashedPassword</a></code>.</p>
 
128
 
 
129
    <h3>The Realm<a name="auto5"/></h3>
 
130
<p>A realm is an interface which connects your universe of <q>business
 
131
objects</q> to the authentication system.</p>
 
132
 
 
133
<p><code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.portal.IRealm.html" title="twisted.cred.portal.IRealm">IRealm</a></code> is another one-method interface:</p>
 
134
 
 
135
<ul>
 
136
<li><code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.portal.IRealm.requestAvatar.html" title="twisted.cred.portal.IRealm.requestAvatar">requestAvatar</a></code><code>(avatarId, mind, *interfaces)</code>
 
137
 
 
138
<p>This method will typically be called from 'Portal.login'.  The avatarId
 
139
is the one returned by a CredentialChecker.</p>
 
140
 
 
141
<div class="note"><strong>Note: </strong>Note that <code>avatarId</code> must always be a string. In
 
142
particular, do not use unicode strings. If internationalized support is needed,
 
143
it is recommended to use UTF-8, and take care of decoding in the realm.  </div>
 
144
 
 
145
<p>The important thing to realize about this method is that if it is being
 
146
called, <em>the user has already authenticated</em>.  Therefore, if possible,
 
147
the Realm should create a new user if one does not already exist
 
148
whenever possible.  Of course, sometimes this will be impossible
 
149
without more information, and that is the case that the interfaces
 
150
argument is for.</p>
 
151
</li>
 
152
</ul>
 
153
 
 
154
<p>Since requestAvatar should be called from a Deferred callback, it may
 
155
return a Deferred or a synchronous result.</p>
 
156
 
 
157
    <h3>The Avatar<a name="auto6"/></h3>
 
158
 
 
159
<p>An avatar is a business logic object for a specific user. For POP3, it's
 
160
a mailbox, for a first-person-shooter it's the object that interacts with
 
161
the game, the actor as it were. Avatars are specific to an application,
 
162
and each avatar represents a single <q>user</q>.</p>
 
163
 
 
164
    <h3>The Mind<a name="auto7"/></h3>
 
165
 
 
166
<p>As mentioned before, the mind is usually None, so you can skip this
 
167
bit if you want.</p>
 
168
 
 
169
<p>Masters of Perspective Broker already know this object as the ill-named
 
170
<q>client object</q>.  There is no <q>mind</q> class, or even interface, but it
 
171
is an object which serves an important role - any notifications which are to be
 
172
relayed to an authenticated client are passed through a 'mind'. In addition, it
 
173
allows passing more information to the realm during login in addition to the
 
174
avatar ID.</p>
 
175
 
 
176
<p>The name may seem rather unusual, but considering that a Mind is
 
177
representative of the entity on the <q>other end</q> of a network connection
 
178
that is both receiving updates and issuing commands, I believe it is
 
179
appropriate.</p>
 
180
 
 
181
<p>Although many protocols will not use this, it serves an important role.
 
182
  It is provided as an argument both to the Portal and to the Realm,
 
183
although a CredentialChecker should interact with a client program
 
184
exclusively through a Credentials instance.</p>
 
185
 
 
186
<p>Unlike the original Perspective Broker <q>client object</q>, a Mind's
 
187
implementation is most often dictated by the protocol that is
 
188
connecting rather than the Realm.  A Realm which requires a particular
 
189
interface to issue notifications will need to wrap the Protocol's mind
 
190
implementation with an adapter in order to get one that conforms to its
 
191
expected interface - however, Perspective Broker will likely continue
 
192
to use the model where the client object has a pre-specified remote
 
193
interface.</p>
 
194
 
 
195
<p>(If you don't quite understand this, it's fine.  It's hard to explain,
 
196
and it's not used in simple usages of cred, so feel free to pass None
 
197
until you find yourself requiring something like this.)</p>
 
198
 
 
199
    <h2>Responsibilities<a name="auto8"/></h2>
 
200
 
 
201
    <h3>Server protocol implementation<a name="auto9"/></h3>
 
202
 
 
203
<p>The protocol implementor should define the interface the avatar should implement,
 
204
and design the protocol to have a portal attached. When a user logs in using the
 
205
protocol, a credential object is created, passed to the portal, and an avatar
 
206
with the appropriate interface is requested. When the user logs out or the protocol
 
207
is disconnected, the avatar should be logged out.</p>
 
208
 
 
209
<p>The protocol designer should not hardcode how users are authenticated or the
 
210
realm implemented. For example, a POP3 protocol implementation would require a portal whose
 
211
realm returns avatars implementing IMailbox and whose credential checker accepts
 
212
username/password credentials, but that is all. Here's a sketch of how the code
 
213
might look - note that USER and PASS are the protocol commands used to login, and
 
214
the DELE command can only be used after you are logged in:</p>
 
215
 
 
216
<pre class="python"><p class="py-linenumber"> 1
 
217
 2
 
218
 3
 
219
 4
 
220
 5
 
221
 6
 
222
 7
 
223
 8
 
224
 9
 
225
10
 
226
11
 
227
12
 
228
13
 
229
14
 
230
15
 
231
16
 
232
17
 
233
18
 
234
19
 
235
20
 
236
21
 
237
22
 
238
23
 
239
24
 
240
25
 
241
26
 
242
27
 
243
28
 
244
29
 
245
30
 
246
31
 
247
32
 
248
33
 
249
34
 
250
35
 
251
36
 
252
37
 
253
38
 
254
39
 
255
40
 
256
41
 
257
42
 
258
43
 
259
44
 
260
45
 
261
46
 
262
47
 
263
48
 
264
49
 
265
50
 
266
51
 
267
52
 
268
53
 
269
54
 
270
55
 
271
56
 
272
57
 
273
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Interface</span>
 
274
 
 
275
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">basic</span>
 
276
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">log</span>
 
277
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">cred</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">credentials</span>, <span class="py-src-variable">error</span>
 
278
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
279
 
 
280
<span class="py-src-keyword">class</span> <span class="py-src-identifier">IMailbox</span>(<span class="py-src-parameter">Interface</span>):
 
281
    <span class="py-src-string">&quot;&quot;&quot;Interface specification for mailbox.&quot;&quot;&quot;</span>
 
282
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">deleteMessage</span>(<span class="py-src-parameter">index</span>): <span class="py-src-keyword">pass</span>
 
283
 
 
284
 
 
285
<span class="py-src-keyword">class</span> <span class="py-src-identifier">POP3</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
 
286
    <span class="py-src-comment"># ...</span>
 
287
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">portal</span>):
 
288
        <span class="py-src-variable">self</span>.<span class="py-src-variable">portal</span> = <span class="py-src-variable">portal</span>
 
289
 
 
290
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">do_DELE</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">i</span>):
 
291
        <span class="py-src-comment"># uses self.mbox, which is set after login</span>
 
292
        <span class="py-src-variable">i</span> = <span class="py-src-variable">int</span>(<span class="py-src-variable">i</span>)-<span class="py-src-number">1</span>
 
293
        <span class="py-src-variable">self</span>.<span class="py-src-variable">mbox</span>.<span class="py-src-variable">deleteMessage</span>(<span class="py-src-variable">i</span>)
 
294
        <span class="py-src-variable">self</span>.<span class="py-src-variable">successResponse</span>()
 
295
 
 
296
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">do_USER</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
 
297
        <span class="py-src-variable">self</span>.<span class="py-src-variable">_userIs</span> = <span class="py-src-variable">user</span>
 
298
        <span class="py-src-variable">self</span>.<span class="py-src-variable">successResponse</span>(<span class="py-src-string">'USER accepted, send PASS'</span>)
 
299
 
 
300
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">do_PASS</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">password</span>):
 
301
        <span class="py-src-keyword">if</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">_userIs</span> <span class="py-src-keyword">is</span> <span class="py-src-variable">None</span>:
 
302
            <span class="py-src-variable">self</span>.<span class="py-src-variable">failResponse</span>(<span class="py-src-string">&quot;USER required before PASS&quot;</span>)
 
303
            <span class="py-src-keyword">return</span>
 
304
        <span class="py-src-variable">user</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">_userIs</span>
 
305
        <span class="py-src-variable">self</span>.<span class="py-src-variable">_userIs</span> = <span class="py-src-variable">None</span>
 
306
        <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">maybeDeferred</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">authenticateUserPASS</span>, <span class="py-src-variable">user</span>, <span class="py-src-variable">password</span>)
 
307
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">_cbMailbox</span>, <span class="py-src-variable">user</span>)
 
308
 
 
309
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">authenticateUserPASS</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>, <span class="py-src-parameter">password</span>):
 
310
        <span class="py-src-keyword">if</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">portal</span> <span class="py-src-keyword">is</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">None</span>:
 
311
            <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">portal</span>.<span class="py-src-variable">login</span>(
 
312
                <span class="py-src-variable">cred</span>.<span class="py-src-variable">credentials</span>.<span class="py-src-variable">UsernamePassword</span>(<span class="py-src-variable">user</span>, <span class="py-src-variable">password</span>),
 
313
                <span class="py-src-variable">None</span>,
 
314
                <span class="py-src-variable">IMailbox</span>
 
315
            )
 
316
        <span class="py-src-keyword">raise</span> <span class="py-src-variable">error</span>.<span class="py-src-variable">UnauthorizedLogin</span>()
 
317
 
 
318
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">_cbMailbox</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">ial</span>, <span class="py-src-parameter">user</span>):
 
319
        <span class="py-src-variable">interface</span>, <span class="py-src-variable">avatar</span>, <span class="py-src-variable">logout</span> = <span class="py-src-variable">ial</span>
 
320
 
 
321
        <span class="py-src-keyword">if</span> <span class="py-src-variable">interface</span> <span class="py-src-keyword">is</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">IMailbox</span>:
 
322
            <span class="py-src-variable">self</span>.<span class="py-src-variable">failResponse</span>(<span class="py-src-string">'Authentication failed'</span>)
 
323
            <span class="py-src-variable">log</span>.<span class="py-src-variable">err</span>(<span class="py-src-string">&quot;_cbMailbox() called with an interface other than IMailbox&quot;</span>)
 
324
            <span class="py-src-keyword">return</span>
 
325
 
 
326
        <span class="py-src-variable">self</span>.<span class="py-src-variable">mbox</span> = <span class="py-src-variable">avatar</span>
 
327
        <span class="py-src-variable">self</span>.<span class="py-src-variable">_onLogout</span> = <span class="py-src-variable">logout</span>
 
328
        <span class="py-src-variable">self</span>.<span class="py-src-variable">successResponse</span>(<span class="py-src-string">'Authentication succeeded'</span>)
 
329
        <span class="py-src-variable">log</span>.<span class="py-src-variable">msg</span>(<span class="py-src-string">&quot;Authenticated login for &quot;</span> + <span class="py-src-variable">user</span>)
 
330
</pre>
 
331
 
 
332
   <h3>Application implementation<a name="auto10"/></h3>
 
333
 
 
334
<p>The application developer can implement realms and credential checkers. For example,
 
335
she might implement a realm that returns IMailbox implementing avatars, using MySQL
 
336
for storage, or perhaps a credential checker that uses LDAP for authentication.
 
337
In the following example, the Realm for a simple remote object service (using
 
338
Twisted's Perspective Broker protocol) is implemented:</p>
 
339
 
 
340
<pre class="python"><p class="py-linenumber"> 1
 
341
 2
 
342
 3
 
343
 4
 
344
 5
 
345
 6
 
346
 7
 
347
 8
 
348
 9
 
349
10
 
350
11
 
351
12
 
352
13
 
353
14
 
354
15
 
355
16
 
356
17
 
357
18
 
358
19
 
359
20
 
360
21
 
361
22
 
362
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">spread</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">pb</span>
 
363
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">cred</span>.<span class="py-src-variable">portal</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">IRealm</span>
 
364
 
 
365
<span class="py-src-keyword">class</span> <span class="py-src-identifier">SimplePerspective</span>(<span class="py-src-parameter">pb</span>.<span class="py-src-parameter">Avatar</span>):
 
366
 
 
367
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">perspective_echo</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">text</span>):
 
368
        <span class="py-src-keyword">print</span> <span class="py-src-string">'echoing'</span>,<span class="py-src-variable">text</span>
 
369
        <span class="py-src-keyword">return</span> <span class="py-src-variable">text</span>
 
370
 
 
371
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">logout</span>(<span class="py-src-parameter">self</span>):
 
372
        <span class="py-src-keyword">print</span> <span class="py-src-variable">self</span>, <span class="py-src-string">&quot;logged out&quot;</span>
 
373
 
 
374
 
 
375
<span class="py-src-keyword">class</span> <span class="py-src-identifier">SimpleRealm</span>:
 
376
    <span class="py-src-variable">implements</span>(<span class="py-src-variable">IRealm</span>)
 
377
 
 
378
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">requestAvatar</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">avatarId</span>, <span class="py-src-parameter">mind</span>, *<span class="py-src-parameter">interfaces</span>):
 
379
        <span class="py-src-keyword">if</span> <span class="py-src-variable">pb</span>.<span class="py-src-variable">IPerspective</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">interfaces</span>:
 
380
            <span class="py-src-variable">avatar</span> = <span class="py-src-variable">SimplePerspective</span>()
 
381
            <span class="py-src-keyword">return</span> <span class="py-src-variable">pb</span>.<span class="py-src-variable">IPerspective</span>, <span class="py-src-variable">avatar</span>, <span class="py-src-variable">avatar</span>.<span class="py-src-variable">logout</span>
 
382
        <span class="py-src-keyword">else</span>:
 
383
            <span class="py-src-keyword">raise</span> <span class="py-src-variable">NotImplementedError</span>(<span class="py-src-string">&quot;no interface&quot;</span>)
 
384
</pre>
 
385
 
 
386
   <h3>Deployment<a name="auto11"/></h3>
 
387
 
 
388
<p>Deployment involves tying together a protocol, an appropriate realm and a credential
 
389
checker. For example, a POP3 server can be constructed by attaching to it a portal
 
390
that wraps the MySQL-based realm and an /etc/passwd credential checker, or perhaps
 
391
the LDAP credential checker if that is more useful. The following example shows
 
392
how the SimpleRealm in the previous example is deployed using an in-memory credential checker:</p>
 
393
 
 
394
<pre class="python"><p class="py-linenumber"> 1
 
395
 2
 
396
 3
 
397
 4
 
398
 5
 
399
 6
 
400
 7
 
401
 8
 
402
 9
 
403
10
 
404
11
 
405
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">spread</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">pb</span>
 
406
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>
 
407
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">cred</span>.<span class="py-src-variable">portal</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Portal</span>
 
408
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">cred</span>.<span class="py-src-variable">checkers</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">InMemoryUsernamePasswordDatabaseDontUse</span>
 
409
 
 
410
<span class="py-src-variable">portal</span> = <span class="py-src-variable">Portal</span>(<span class="py-src-variable">SimpleRealm</span>())
 
411
<span class="py-src-variable">checker</span> = <span class="py-src-variable">InMemoryUsernamePasswordDatabaseDontUse</span>()
 
412
<span class="py-src-variable">checker</span>.<span class="py-src-variable">addUser</span>(<span class="py-src-string">&quot;guest&quot;</span>, <span class="py-src-string">&quot;password&quot;</span>)
 
413
<span class="py-src-variable">portal</span>.<span class="py-src-variable">registerChecker</span>(<span class="py-src-variable">checker</span>)
 
414
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">listenTCP</span>(<span class="py-src-number">9986</span>, <span class="py-src-variable">pb</span>.<span class="py-src-variable">PBServerFactory</span>(<span class="py-src-variable">portal</span>))
 
415
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
 
416
</pre>
 
417
 
 
418
   <h2>Cred plugins<a name="auto12"/></h2>
 
419
 
 
420
   <h3>Authentication with cred plugins<a name="auto13"/></h3>
 
421
 
 
422
<p> Cred offers a plugin architecture for authentication methods. The
 
423
primary API for this architecture is the command-line; the plugins are
 
424
meant to be specified by the end-user when deploying a TAP (twistd
 
425
plugin).</p>
 
426
 
 
427
<p> For more information on writing a twistd plugin and using cred
 
428
plugins for your application, please refer to the <a href="tap.html" shape="rect">Writing a twistd plugin</a> document.</p>
 
429
 
 
430
   <h3>Building a cred plugin<a name="auto14"/></h3>
 
431
 
 
432
<p> To build a plugin for cred, you should first define an <code class="python">authType</code>, a short one-word string that defines
 
433
your plugin to the command-line. Once you have this, the convention is
 
434
to create a file named <code>myapp_plugins.py</code> in the
 
435
<code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.plugins.html" title="twisted.plugins">twisted.plugins</a></code> module path. </p>
 
436
 
 
437
<p> Below is an example file structure for an application that defines
 
438
such a plugin: </p>
 
439
 
 
440
<ul>
 
441
<li>MyApplication/
 
442
  <ul>
 
443
  <li>setup.py</li>
 
444
  <li>myapp/
 
445
    <ul>
 
446
    <li>__init__.py</li>
 
447
    <li>cred.py</li>
 
448
    <li>server.py</li>
 
449
    </ul>
 
450
  </li>
 
451
  <li>twisted/
 
452
    <ul>
 
453
    <li>plugins/
 
454
      <ul>
 
455
      <li>myapp_plugins.py</li>
 
456
      </ul>
 
457
    </li>
 
458
    </ul>
 
459
  </li>
 
460
  </ul>
 
461
</li>
 
462
</ul>
 
463
 
 
464
<p>
 
465
Once you have created this structure within your application, you can
 
466
create the code for your cred plugin by building a factory class which
 
467
implements <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.cred.checkers.ICheckerFactory.html" title="twisted.cred.checkers.ICheckerFactory">ICheckerFactory</a></code>.
 
468
These factory classes should not consist of a tremendous amount of
 
469
code. Most of the real application logic should reside in the cred
 
470
checker itself. (For help on building those, scroll up.)
 
471
</p>
 
472
 
 
473
<p>
 
474
The core purpose of the CheckerFactory is to translate an <code class="python">argstring</code>, which is passed on the command line,
 
475
into a suitable set of initialization parameters for a Checker
 
476
class. In most cases this should be little more than constructing a
 
477
dictionary or a tuple of arguments, then passing them along to a new
 
478
checker instance.
 
479
</p>
 
480
 
 
481
<pre class="python"><p class="py-linenumber"> 1
 
482
 2
 
483
 3
 
484
 4
 
485
 5
 
486
 6
 
487
 7
 
488
 8
 
489
 9
 
490
10
 
491
11
 
492
12
 
493
13
 
494
14
 
495
15
 
496
16
 
497
17
 
498
18
 
499
19
 
500
20
 
501
21
 
502
22
 
503
23
 
504
24
 
505
25
 
506
26
 
507
27
 
508
28
 
509
29
 
510
30
 
511
31
 
512
32
 
513
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">implements</span>
 
514
 
 
515
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">plugin</span>
 
516
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">cred</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">checkers</span>
 
517
<span class="py-src-keyword">from</span> <span class="py-src-variable">myapp</span>.<span class="py-src-variable">cred</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">SpecialChecker</span>
 
518
 
 
519
<span class="py-src-keyword">class</span> <span class="py-src-identifier">SpecialCheckerFactory</span>(<span class="py-src-parameter">object</span>):
 
520
    <span class="py-src-string">&quot;&quot;&quot;
 
521
    A checker factory for a specialized (fictional) API.
 
522
    &quot;&quot;&quot;</span>
 
523
    <span class="py-src-comment"># The class needs to implement both of these interfaces</span>
 
524
    <span class="py-src-comment"># for the plugin system to find our factory.</span>
 
525
    <span class="py-src-variable">implements</span>(<span class="py-src-variable">checkers</span>.<span class="py-src-variable">ICheckerFactory</span>, <span class="py-src-variable">plugin</span>.<span class="py-src-variable">IPlugin</span>)
 
526
 
 
527
    <span class="py-src-comment"># This tells AuthOptionsMixin how to find this factory.</span>
 
528
    <span class="py-src-variable">authType</span> = <span class="py-src-string">&quot;special&quot;</span>
 
529
 
 
530
    <span class="py-src-comment"># This is a one-line explanation of what arguments, if any,</span>
 
531
    <span class="py-src-comment"># your particular cred plugin requires at the command-line.</span>
 
532
    <span class="py-src-variable">argStringFormat</span> = <span class="py-src-string">&quot;A colon-separated key=value list.&quot;</span>
 
533
 
 
534
    <span class="py-src-comment"># This help text can be multiple lines. It will be displayed</span>
 
535
    <span class="py-src-comment"># when someone uses the &quot;--help-auth-type special&quot; command.</span>
 
536
    <span class="py-src-variable">authHelp</span> = <span class="py-src-string">&quot;&quot;&quot;Some help text goes here ...&quot;&quot;&quot;</span>
 
537
 
 
538
    <span class="py-src-comment"># This will be called once per command-line.</span>
 
539
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">generateChecker</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">argstring</span>=<span class="py-src-string">&quot;&quot;</span>):
 
540
        <span class="py-src-variable">argdict</span> = <span class="py-src-variable">dict</span>((<span class="py-src-variable">x</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">'='</span>) <span class="py-src-keyword">for</span> <span class="py-src-variable">x</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">argstring</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">':'</span>)))
 
541
        <span class="py-src-keyword">return</span> <span class="py-src-variable">SpecialChecker</span>(**<span class="py-src-variable">dict</span>)
 
542
 
 
543
<span class="py-src-comment"># We need to instantiate our class for the plugin to work.</span>
 
544
<span class="py-src-variable">theSpecialCheckerFactory</span> = <span class="py-src-variable">SpecialCheckerFactory</span>()
 
545
</pre>
 
546
 
 
547
<p> For more information on how your plugin can be used in your
 
548
application (and by other application developers), please see the <a href="tap.html" shape="rect">Writing a twistd plugin</a> document.</p>
 
549
 
 
550
<h2>Conclusion<a name="auto15"/></h2>
 
551
 
 
552
<p>After reading through this tutorial, you should be able to
 
553
</p>
 
554
<ul>
 
555
<li>Understand how the cred architecture applies to your application</li>
 
556
<li>Integrate your application with cred's object model</li>
 
557
<li>Deploy an application that uses cred for authentication</li>
 
558
<li>Allow your users to use command-line authentication plugins</li>
 
559
</ul>
 
560
 
 
561
</div>
 
562
 
 
563
    <p><a href="index.html">Index</a></p>
 
564
    <span class="version">Version: 10.0.0</span>
 
565
  </body>
 
566
</html>
 
 
b'\\ No newline at end of file'